Mybatis自定义TypeHandler解决特殊类型转换问题详解
我们知道,Java和MySQL中的数据类型是不同的,Java中除了基本数据类型,还有对象。
有时候使用MySQL存储数据,或者从MySQL中读取数据时,会有一些特殊需求weary,比如:
- 将Integer数组直接存入MySQL,保存为BLOB形式,读取出来时又是正常的Integer数组
- 将Integer数组转换为String,然后存入MySQL,使用varchar类型,读取出来时又是正常的Integer数组
这也太难了叭!
解决办法有两种:
- BasicMethod:Java在存入数据之前,或读取数据之后,做手动类型转换
- CleverMethod:定义TypeHandler,并在Mybatis对应位置指明
关于第一种方法这里不予赘述,不够Smart。这里主要讲述如何自定义Handler,来解决Java数据->MySQL数据的特殊类型转换问题grinning
这种Handler不仅方便了我们的数据库操作,还有利于代码的复用。
这里以Integer[]数组的存储为形如,1,2,3,的varchar字符串为例。
问题示例
我们定义一个role类,与数据库的role表对应:
publicclassRole{ privateIntegerid; privateStringname; privateInteger[]accessIds; privateDatecreateTime; //...ignoregetandsetmethods }
注意到里面有一个accessIds字段,它的类型是Integer[]
数据库设计:
DROPTABLEIFEXISTS`role`; CREATETABLE`role`( `id`int(11)NOTNULLAUTO_INCREMENT, `name`varchar(255)NOTNULL, `access_ids`varchar(255)DEFAULTNULL, `create_time`datetimeNOTNULL, PRIMARYKEY(`id`) )ENGINE=InnoDBAUTO_INCREMENT=2DEFAULTCHARSET=utf8; ------------------------------ --Recordsofrole ------------------------------ INSERTINTO`role`VALUES('1','测试角色',',1,2,','2019-11-1413:43:14');
自定义Handler类
通过继承BaseTypeHandler类,重写其方法,定义一个Integer[]与数据库varchar类型自动转换的Handler类:
/** *JavaInt数组与MySQLString转换器 *比如[1,2,3]-->",1,2,3," */ publicclassStringToIntArrayHandlerextendsBaseTypeHandler{ privatestaticfinalStringsplitCharset=","; @Override publicvoidsetNonNullParameter(PreparedStatementps,inti,Integer[]objects,JdbcTypejdbcType)throwsSQLException{ Stringstr=arrayToString(objects); ps.setString(i,str); } @Override publicInteger[]getNullableResult(ResultSetrs,StringcolumnName)throwsSQLException{ Stringstr=rs.getString(columnName); returnstringToArray(str); } @Override publicInteger[]getNullableResult(ResultSetrs,intcolumnIndex)throwsSQLException{ Stringstr=rs.getString(columnIndex); returnstringToArray(str); } @Override publicInteger[]getNullableResult(CallableStatementcs,intcolumnIndex)throwsSQLException{ Stringstr=cs.getString(columnIndex); returnstringToArray(str); } //---privatemethods--- /** *Integer数组转String *注:使用提前设定好的分隔符分割数组的每一项 */ privatestaticStringarrayToString(Integer[]array){ StringBuilderres=newStringBuilder(); if(array!=null&&array.length>0){ for(Objecto:array){ res.append(splitCharset).append(o.toString()); } res.append(splitCharset); } returnres.length()>0?res.toString():null; } /** *从String转Integer数组 *注:String是用分隔符分割的,使用String.split方法可以分解为数组 */ privatestaticInteger[]stringToArray(Stringstr){ List list=newArrayList<>(); if(str!=null){ String[]array=str.split(splitCharset); if(array.length>0){ for(Stringo:array){ if(o!=null&&o.length()>0){ list.add(Integer.parseInt(o)); } } } } returnlist.toArray(newInteger[0]); } }
这个类的具体作用是什么呢?
- 当Java中类型是Integer[]时,使用这个Handler类,将Integer[]转换为以,号分割的字符串,然后存入数据库
- 当从数据库读取以,分割值的字符串时,可以通过这个Handler,自动将字符串转换为Integer[]数组
下面我们演示一下具体的使用smile
在Mybatis中应用自定义的Handler
Mybatis存放SQL语句的XML文件:
SELECTid,name,access_ids,create_time FROMrole WHEREid=#{id} SELECTLAST_INSERT_ID() INSERTINTOrole (name,create_time,access_ids) VALUES (#{name},#{createTime} ,#{accessIds,jdbcType=VARCHAR,typeHandler=com.example.model.dao.handler.StringToIntArrayHandler})
以上XML中演示了select和insert两种情况时,如何应用typeHandler。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。