概述
场景:
在做开发时,我们经常会遇到这样一些问题,比如我有一个Java中的Date数据类型,我想将之存到数据库的时候存成一个1970年至今的毫秒数,怎么实现?再比如我有一个Student类,Student类中有一个属性叫做hobbys,这个属性用来描述学生的爱好,它的数据类型是一个List<String>集合,那么我想在把这个List集合存入数据库的时候能够自动的变成{XXX,XXX,XXX}这样一个字符串然后存起来,当我从数据库读取的时候也是读取到这样一个字符串,读取成功之后再自动的将之转为一个List集合,OK,以上两种需求用我们传统的数据库读写操作肯定都是可以实现的,只不过工作量略大,在mybatis中有一个功能略强大的typeHandler专门用来解决数据库中的数据类型和Java中的数据类型之间的转化问题,那么我们今天以上面第二种需求为例,来看看typeHandler要怎么使用。
构建:
数据库结构如图所示:
实体类结构如图所示:
重写TypeHandler接口
自定义类型处理器是通过实现 org.apache.ibatis.type.TypeHandler 接口实现的。这个接口定义了类型处理器的基本功能,接口定义如下所示。
其中,泛型T专指javaType。 setParameter 方法用于把 java 对象设置到 PreparedStatement 的参数中,getResult 方法用于从 ResultSet(根据列名或者索引位置获取) 或 CallableStatement(根据存储过程获取) 中取出数据转换为 java 对象。自定义typeHandler如下:
//这个注解定义的是JdbcType类型,这里的类型不可自己随意定义,必须要是枚举类org.apache.ibatis.type.JdbcType所枚举的数据类型
@MappedJdbcTypes({JdbcType.VARCHAR})
//这里定义的是JavaType的数据类型,描述了哪些Java类型可被拦截
@MappedTypes({List.class})
public class ListTypeHandler implements TypeHandler<List<String>> {
@Override
public void setParameter(PreparedStatement ps, int i, List<String> parameter, JdbcType jdbcType) throws SQLException {
String hobbys = StringUtils.join(parameter, ",");
try {
ps.setString(i, hobbys);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public List<String> getResult(ResultSet rs, String columnName) throws SQLException {
return Arrays.asList(rs.getString(columnName).split(","));
}
@Override
public List<String> getResult(ResultSet rs, int columnIndex) throws SQLException {
return Arrays.asList(rs.getString(columnIndex).split(","));
}
@Override
public List<String> getResult(CallableStatement cs, int columnIndex) throws SQLException {
String hobbys = cs.getString(columnIndex);
return Arrays.asList(hobbys.split(","));
}
}
注册:
因为这是mybatis的功能,可以在mybatis的全局配置文件(mybatis-config.xml)中进行配置:
<configuration>
<typeHandlers>
<!--
当配置package的时候,mybatis会去配置的package扫描TypeHandler
<package name="com.dy.demo"/>
-->
<!-- handler属性直接配置我们要指定的TypeHandler -->
<typeHandler handler=""/>
<!-- javaType 配置java类型,例如String, 如果配上javaType, 那么指定的typeHandler就只作用于指定的类型 -->
<typeHandler javaType="" handler=""/>
<!-- jdbcType 配置数据库基本数据类型,例如varchar, 如果配上jdbcType, 那么指定的typeHandler就只作用于指定的类型 -->
<typeHandler jdbcType="" handler=""/>
<!-- 也可两者都配置 -->
<typeHandler javaType="" jdbcType="" handler=""/>
</typeHandlers>
......
</configuration>
但是对于我们现在的开发环境来说,spring太流行了,typeHandler也可以直接在spring的配置文件中进行配置(我这里是在spring-mybatis中配置的):
<!-- 使用spring的方式声明typeHandler-->
<bean id="listStringTypeHandler" class="common.ListTypeHandler"/>
<!-- mybatis文件配置,配置SqlSessionFactoryBean类,扫描所有mapper文件 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 指定数据源 -->
<property name="dataSource" ref="dataSource"/>
<property name="mapperLocations" value="classpath:mapping/*Mapper.xml"/>
<!--typeHandler注入-->
<property name="typeHandlers" ref="listStringTypeHandler"/>
</bean>
配置完成之后,当jdbcType和javaType能与ListTypeHandler对应时,就会调用自定义的ListTypeHandler进行数据转换。有时候我们还可以显示的启动typeHandler。一般有两种方式:
##在Mapper中进行配置
自定义好了typeHandler之后,接下来我们需要在studentMapper.xml中进行简单的配置,首先我们可以像上文说的,配置resultMap,如下:
<resultMap id="BaseResultMap" type="entity.Student">
<constructor>
<idArg column="id" javaType="java.lang.String" jdbcType="VARCHAR" />
<arg column="name" javaType="java.lang.String" jdbcType="VARCHAR" />
<arg column="sex" javaType="java.lang.String" jdbcType="VARCHAR" />
<arg column="rank" javaType="java.lang.Integer" jdbcType="INTEGER" />
<arg column="create_date" javaType="java.util.Date" jdbcType="TIMESTAMP" />
<arg column="update_date" javaType="java.util.Date" jdbcType="TIMESTAMP" />
<arg typeHandler="common.ListTypeHandler" column="hobbys" javaType="java.util.List"
jdbcType="VARCHAR"/>
</constructor>
</resultMap>
配置resultMap的时候我们指定了javaType和jdbcType,同时也指定了处理的typeHandler,然后在select中使用这个resultMap:但是这种方式有一个缺点那就是只适用于查询操作,即在查询的过程中系统会启用我们自定义的typeHandler,会将秒数转为List对象,但是在插入的时候却不会启用我们自定义的typeHandler,想要在插入的时候启用自定义的typeHandler,需要我们在insert节点中简单配置一下,如下:
<insert id="insert" parameterType="entity.Student">
insert into student (id, name, sex,
rank, create_date, update_date,
hobbys)
values (#{id,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, #{sex,jdbcType=VARCHAR},
#{rank,jdbcType=INTEGER}, #{createDate,jdbcType=TIMESTAMP}, #{updateDate,jdbcType=TIMESTAMP},
#{hobbys,javaType=List,jdbcType=VARCHAR,typeHandler=common.ListTypeHandler})
</insert>
或者只配置typeHandler:
<insert id="insert" parameterType="entity.Student">
insert into student (id, name, sex,
rank, create_date, update_date,
hobbys)
values (#{id,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, #{sex,jdbcType=VARCHAR},
#{rank,jdbcType=INTEGER}, #{createDate,jdbcType=TIMESTAMP}, #{updateDate,jdbcType=TIMESTAMP},
#{hobbys,typeHandler=common.ListTypeHandler})
</insert>
参考资料:
https://blog.csdn.net/u012702547/article/details/54572679
https://blog.csdn.net/zhaoyf7746/article/details/71131578
最后
以上就是香蕉洋葱为你收集整理的mybatis--自定义typeHandler的使用的全部内容,希望文章能够帮你解决mybatis--自定义typeHandler的使用所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复