MyBatis中自定义typeHandler
Mybatis中的TypeHandler是什么?
无论是 MyBatis 在预处理语句(PreparedStatement)中设置一个参数时,还是从结果集中取出一个值时,都会用类型处理器将获取的值以合适的方式转换成 Java 类型。Mybatis默认为我们实现了许多TypeHandler, 当我们没有配置指定TypeHandler时,Mybatis会根据参数或者返回结果的不同,默认为我们选择合适的TypeHandler处理。
typeHandlers
无论是 MyBatis 在预处理语句(PreparedStatement)中设置一个参数时,还是从结果集中取出一个值时, 都会用类型处理器将获取的值以合适的方式转换成 Java 类型。下表描述了一些默认的类型处理器。
提示 从 3.4.5 开始,MyBatis 默认支持 JSR-310(日期和时间 API) 。
使用场景:mybatis在预处理语句(PreparedStatement)中设置一个参数时,或者从结果集(ResultSet)中取出一个值时,都会用到TypeHandler。它的作用就是将java类型(javaType)转化为jdbc类型(jdbcType),或者将jdbc类型(jdbcType)转化为java类型(javaType)。
需求一:
自定义枚举类型的TypeHandler,我们通过User类中有一个属性性别(Sex)类型,来实现数据库存sexcode, 取数据出来是sexname
需求二:
User类中有一个属性叫做interest,这个属性用来描述用户的爱好,它的数据类型是一个List集合,那么我想在把这个List集合存入数据库的时候能够自动的变成{XXX,XXX,XXX}这样一个字符串然后存起来,当我从数据库读取的时候也是读取到这样一个字符串,读取成功之后再自动的将之转为一个List集合,
系统提供的typeHandler能够满足我们日常开发中的大部分需求,如上这两种特殊的需求就需要我们自己去定义typeHandler了
1、自定义Sex枚举类型(需求一)
public enum SexEnum {
MALE(1,"男"),
FMALE(0,"女");
private int sexCode;
private String sexName;
private SexEnum(int sexCode, String sexName) {
this.sexCode = sexCode;
this.sexName = sexName;
}
//通过SexCode的值来获取Sex枚举类型
public static SexEnum getSexEnumFromCode(int sexCode) {
if(sexCode == 1) {
return MALE;
}else if(sexCode == 0) {
return FMALE;
}
return null;
}
//get set
}
2、 自定义枚举类型的TypeHandler
** 自定义typeHandler我们有两种方式,一种是实现TypeHandler接口,还有一种就是继承自BaseTypeHandler类。**
@MappedJdbcTypes() 定义的是JdbcType类型,这里的类型不可自己随意定义,**必须要是枚举类**org.apache.ibatis.type.JdbcType所枚举的数据类型。
@MappedTypes() 定义的是JavaType的数据类型,描述了哪些Java类型可被拦截。
在我们启用了我们自定义的这个TypeHandler之后,数据的读写都会被这个类所过滤
在setNonNullParameter / setParameter方法中,我们重新定义要写往数据库的数据。
另外三个方法中我们将从数据库读出的数据类型进行转换
**采用注解 或者 sql映射文件指定 JdbcType 和 JavaType 都可以**
1) sex属性类型用自定义Sex枚举类型的TypeHandler(需求一)
public class MySexTypeHandler implements TypeHandler<SexEnum>{
@Override
public void setParameter(PreparedStatement ps, int i, SexEnum parameter, JdbcType jdbcType) throws SQLException {
ps.setInt(i, parameter.getSexCode());
}
@Override
public SexEnum getResult(ResultSet rs, String columnName) throws SQLException {
int sexCode = rs.getInt(columnName);
return SexEnum.getSexEnumFromCode(sexCode);
}
@Override
public SexEnum getResult(ResultSet rs, int columnIndex) throws SQLException {
int sexCode = rs.getInt(columnIndex);
return SexEnum.getSexEnumFromCode(sexCode);
}
@Override
public SexEnum getResult(CallableStatement cs, int columnIndex) throws SQLException {
int sexCode = cs.getInt(columnIndex);
return SexEnum.getSexEnumFromCode(sexCode);
}
}
2)interest属性类型用自定义List类型的TypeHandler(需求二) 采用注释
@MappedTypes(List.class)
@MappedJdbcTypes({JdbcType.VARCHAR})
public class MyListTypeHandler extends BaseTypeHandler<List<String>>{
@Override
public void setNonNullParameter(PreparedStatement ps, int i, List<String> parameter, JdbcType jdbcType)
throws SQLException {
if(parameter != null) {
// List集合转字符串
StringBuffer sbBuffer = new StringBuffer();
for(String string : parameter) {
sbBuffer.append(string).append(",");
}
ps.setString(i, sbBuffer.toString().substring(0,sbBuffer.toString().length()-1));
}
}
@Override
public List<String> getNullableResult(ResultSet rs, String columnName) throws SQLException {
if(rs.getString(columnName) != null) {
String[] split = rs.getString(columnName).split(",");
return Arrays.asList(split);
}
return null;
}
@Override
public List<String> getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
String[] split = rs.getString(columnIndex).split(",");
return Arrays.asList(split);
}
@Override
public List<String> getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
String[] split = cs.getString(columnIndex).split(",");
return Arrays.asList(split);
}
}
3、 数据库 与 java model类
sex属性类型用自定义SexEnum 枚举类型
public class User {
private Integer id;
private String username;
private String pazzword;
private Integer state;
private Date regDate;
private SexEnum sex; // 1:男, 0:女,用枚举
private List<String> interest; //爱好
...}
4、在sql映射文件中进行配置
注意: 获取数据和插入数据 的 配置
<resultMap id="BaseResultMap" type="cn.jq.mybatis.model.User">
<id column="id" jdbcType="INTEGER" property="id" />
<result column="username" jdbcType="VARCHAR" property="username" />
<result column="pazzword" jdbcType="VARCHAR" property="pazzword" />
<result column="state" jdbcType="INTEGER" property="state" />
<result column="reg_date" jdbcType="TIMESTAMP" property="regDate" />
<result column="sex" property="sex"
jdbcType="INTEGER"
javaType="cn.jq.mybatis.enums.SexEnum"
typeHandler="cn.jq.mybatis.enums.MySexTypeHandler"/>
<result column="interest" property="interest"
typeHandler="cn.jq.mybatis.enums.MyListTypeHandler"/>
</resultMap>
<sql id="Base_Column_List">
id, username, pazzword, state, reg_date, sex, interest
</sql>
<select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">
select
<include refid="Base_Column_List" />
from t_user
where id = #{id,jdbcType=INTEGER}
</select>
<insert id="insertUser" >
insert into t_user
(username,pazzword,state,reg_date,sex,interest)
values
(#{username},#{pazzword},#{state},#{regDate},
#{sex, jdbcType=INTEGER, javaType=cn.jq.mybatis.enums.SexEnum, typeHandler=cn.jq.mybatis.enums.MySexTypeHandler},
#{interest, typeHandler=cn.jq.mybatis.enums.MyListTypeHandler})
</insert>
5、在全局配置文件中注册自定义的typeHandler
注意标签配置顺序: 在 set 标签之后
<typeHandlers>
<typeHandler handler="cn.jq.mybatis.enums.MyListTypeHandler" />
<typeHandler handler="cn.jq.mybatis.enums.MySexTypeHandler" />
</typeHandlers>
6、测试
1)insert数据
UserMapper userMapper = session.getMapper(UserMapper.class);
List<String> list = new ArrayList<String>();
list.add("足球");
list.add("排球");
list.add("音乐");
User user = new User();
user.setUsername("ad22");
user.setPazzword("pass22");
user.setState(1);
user.setRegDate(new Date());
user.setSex(SexEnum.FMALE);
//user.setInterest(null); //爱好为空,自定义typeHandle做了判断
user.setInterest(list);
userMapper.insertUser(user);
session.commit();
System.out.println(user);
数据库:
2)select 数据
User user1 = userMapper.selectByPrimaryKey(1);
System.out.println(user1);
#
小结
OK,经过上面的介绍,想必小伙伴对typeHandler的使用已经有一定了解了,总结一下就是读取时的配置要和插入时的配置分开来做,
读取时数据转换我们有两种配置方式,分别是resultMap和在mybatis配置文件中配置typeHandlers,
插入时的配置就是在insert节点中进行配置。
参考文章:
https://blog.csdn.net/u012702547/article/details/54572679
https://www.cnblogs.com/dongying/p/4040435.html
还没有评论,来说两句吧...