mybatis自定义typeHandler映射对象为JSON.docx
《mybatis自定义typeHandler映射对象为JSON.docx》由会员分享,可在线阅读,更多相关《mybatis自定义typeHandler映射对象为JSON.docx(9页珍藏版)》请在冰豆网上搜索。
![mybatis自定义typeHandler映射对象为JSON.docx](https://file1.bdocx.com/fileroot1/2022-11/16/1f8e1021-dd83-42b4-8636-78bc313e6832/1f8e1021-dd83-42b4-8636-78bc313e68321.gif)
mybatis自定义typeHandler映射对象为JSON
mybatis自定义typeHandler映射对象为JSON
mybatis自定义typeHandler映射对象为JSON2012-02-1417:
12:
43|分类:
web|字号订阅技术背景:
一个domain对象不可避免的会出现List、Map类型的字段,或者将多个字段拼装到一个字段的情况。
前者存在是业务及设计的需求,后者出现是当初设计数据库没有考虑那么多字段,业务快速发展时需要增加字段,数据库数据量大时,添加一个字段非常耗时,有可能中断服务。
为保证服务的可用性,及减少数据订正麻烦,应对频繁的业务变更,会把几个字段拼接到一个字段中。
这些字段在domain对象中往往采用下面的方式进行处理:
解析字段成需要的类型,拼接多个字段填充成一个字段。
操作过程类似下面的代码:
publicclassUserimplementsSerializable{
privatestaticfinallongserialVersionUID=-3120416800441648924L;
privateList<String>hobbys;//存储hobbys
privateStringhobbyExt;
privateStringext1;
privateStringext2;
privateStringext3;
//存储ext1、ext2、ext3的信息
privateStringextInfo;
publicStringgetExtInfo(){
returnextInfo;
}
publicvoidsetExtInfo(StringextInfo){
this.extInfo=extInfo;
}
publicStringgetExt1(){
returnext1;
}
publicvoidsetExt1(Stringext1){
this.ext1=ext1;
}
publicStringgetExt2(){
returnext2;
}
publicvoidsetExt2(Stringext2){
this.ext2=ext2;
}
publicStringgetExt3(){
returnext3;
}
publicvoidsetExt3(Stringext3){
this.ext3=ext3;
}
publicList<String>getHobbys(){
this.parseInfo();
returnhobbys;
}
publicvoidparseInfo(){
//TODO解析字段hobbyExt成hobbys,将extInfo解析成ext1、ext2、ext3
}
publicvoidfillExtendInfo(){
//TODO将Listhobbys拼装成一个字符串,ext1、ext2、ext3拼接成一个字符串
}
publicStringgetHobbyExt(){
returnhobbyExt;
}
publicvoidsetHobbyExt(StringhobbyExt){
this.hobbyExt=hobbyExt;
}
publicvoidsetHobbys(List<String>hobbys){
this.hobbys=hobbys;
}
}这样处理操作繁琐,程序进行存取时要注意解析及填充操作,如果一旦忽略或误用了某个操作,会导致数据库中某个信息没被填充进去,或者产生一些脏数据,极易引入潜在的bug。
领一种解决解决方法是将解析及填充操作放到DO对象的set及get方法中,类似下面的代码:
publicList<String>getHobbys(){
this.parseInfo();
returnhobbys;
}这种处理方式会导致每次存取该字段时都要进行解析操作,增加了不必要的性能开销。
不同程序员对不同domain对象定义难以想用,这种解析操作无法共用。
如果要增加附加字段,需修改原有的解析方法,又增加了引入bug的风险。
这种拼接,解析操作也减低了程序的易读性,导致可维护性降低。
如何避免这种拼接及解析的操作,创建一个干净的domain对象呢?
下面是一个干净的domain对象及其对应的ibatis的的映射文件配置:
UserDO对象:
//UserDO对象publicclassUserDOimplementsSerializable{
privatestaticfinallongserialVersionUID=377875304139361819L;
privateintid;
privateStringname;
privateUserExtDOextDO;
privateList<String>hobbys;
privateMap<String,String>votes;
publicMap<String,String>getVotes(){
returnvotes;
}
publicvoidsetVotes(Map<String,String>votes){
this.votes=votes;
}
publicvoidaddHobby(Stringhobby){
if(hobbys==null){
hobbys=newArrayList<String>();
}
hobbys.add(hobby);
}
publicList<String>getHobbys(){
returnhobbys;
}
publicvoidsetHobbys(List<String>hobbys){
this.hobbys=hobbys;
}
publicintgetId(){
returnid;
}
publicvoidsetId(intid){
this.id=id;
}
publicStringgetName(){
returnname;
}
publicvoidsetName(Stringname){
this.name=name;
}
publicUserExtDOgetExtDO(){
returnextDO;
}
publicvoidsetExtDO(UserExtDOextDO){
this.extDO=extDO;
}
}//其扩展字段的对象publicclassUserExtDOimplementsSerializable{
privatestaticfinallongserialVersionUID=-6065939028174333314L;
privateStringschool;
privateList<String>loves;
publicStringgetSchool(){
returnschool;
}
publicvoidsetSchool(Stringschool){
this.school=school;
}
publicList<String>getLoves(){
returnloves;
}
publicvoidsetLoves(List<String>loves){
this.loves=loves;
}
publicvoidaddLove(Stringlove){
if(loves==null){
loves=newArrayList<String>();
}
loves.add(love);
}
}UserDO的ORM映射文件:
<?
xmlversion="1.0"encoding="UTF-8"?
>
<!
DOCTYPEmapperPUBLIC"-//mybatis.org//DTDMapper3.0//EN"
"http:
//mybatis.org/dtd/mybatis-3-mapper.dtd">
<mappernamespace="UserDO">
<resultMaptype="UserDO"id="UserDO">
<idproperty="id"column="id"/>
<resultproperty="name"column="name"/>
<resultproperty="extDO"column="extDO"/>
</resultMap>
<parameterMaptype="UserDO"id="UserDO">
<parameterproperty="id"/>
<parameterproperty="name"/>
<parameterproperty="extDO"/>
</parameterMap>
<selectid="selectAllUsers"resultType="UserDO">
select*fromuser
</select>
<insertid="insertUser"parameterType="UserDO">
insertintouser(id,name,extDO,hobbys,votes)
values(#{id},#{name},#{extDO},#{hobbys},#{votes});
</insert>
<selectid="mapTest"resultType="UserDO">
select*fromuserwherevoteslike#{keyword}
</select>
</mapper>查看UserDO映射文件,extDO字段是一个对象,程序中没有任何拼接代码,怎么能存到数据库中呢?
数据库中该字段时什么类型呢?
数据库中extDO的类型如下图:
extDO字段是Text类型。
UserExtDO对象存储到一个text类型的字段上了,这是如何实现的呢?
这就要靠mybatis提供的自定义类型处理器功能了。
MyBatis在预处理语句中设置一个参数,或从结果集中获取一个值时,会使用类型处理器typeHandler将获取的值以合适的方式转换成Java类型。
数据库中的基本类型之所以能被mybatis转换成Java类型,是因为mybatis已经内置了这些类型的处理器,如下图是mybatis内置的部分处理器:
除内置的类型处理器外,mybatis同时提供了类型处理器的扩展功能,允许程序自定类型处理器,或者替换