MyBatis中自定义typeHandler

短命女 2022-04-14 02:06 349阅读 0赞

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枚举类型(需求一)

  1. public enum SexEnum {
  2. MALE(1,"男"),
  3. FMALE(0,"女");
  4. private int sexCode;
  5. private String sexName;
  6. private SexEnum(int sexCode, String sexName) {
  7. this.sexCode = sexCode;
  8. this.sexName = sexName;
  9. }
  10. //通过SexCode的值来获取Sex枚举类型
  11. public static SexEnum getSexEnumFromCode(int sexCode) {
  12. if(sexCode == 1) {
  13. return MALE;
  14. }else if(sexCode == 0) {
  15. return FMALE;
  16. }
  17. return null;
  18. }
  19. //get set
  20. }

2、 自定义枚举类型的TypeHandler

  1. ** 自定义typeHandler我们有两种方式,一种是实现TypeHandler接口,还有一种就是继承自BaseTypeHandler类。**
  2. @MappedJdbcTypes() 定义的是JdbcType类型,这里的类型不可自己随意定义,**必须要是枚举类**org.apache.ibatis.type.JdbcType所枚举的数据类型。
  3. @MappedTypes() 定义的是JavaType的数据类型,描述了哪些Java类型可被拦截。
  4. 在我们启用了我们自定义的这个TypeHandler之后,数据的读写都会被这个类所过滤
  5. setNonNullParameter / setParameter方法中,我们重新定义要写往数据库的数据。
  6. 另外三个方法中我们将从数据库读出的数据类型进行转换
  7. **采用注解 或者 sql映射文件指定 JdbcType JavaType 都可以**

1) sex属性类型用自定义Sex枚举类型的TypeHandler(需求一)

  1. public class MySexTypeHandler implements TypeHandler<SexEnum>{
  2. @Override
  3. public void setParameter(PreparedStatement ps, int i, SexEnum parameter, JdbcType jdbcType) throws SQLException {
  4. ps.setInt(i, parameter.getSexCode());
  5. }
  6. @Override
  7. public SexEnum getResult(ResultSet rs, String columnName) throws SQLException {
  8. int sexCode = rs.getInt(columnName);
  9. return SexEnum.getSexEnumFromCode(sexCode);
  10. }
  11. @Override
  12. public SexEnum getResult(ResultSet rs, int columnIndex) throws SQLException {
  13. int sexCode = rs.getInt(columnIndex);
  14. return SexEnum.getSexEnumFromCode(sexCode);
  15. }
  16. @Override
  17. public SexEnum getResult(CallableStatement cs, int columnIndex) throws SQLException {
  18. int sexCode = cs.getInt(columnIndex);
  19. return SexEnum.getSexEnumFromCode(sexCode);
  20. }
  21. }

2)interest属性类型用自定义List类型的TypeHandler(需求二) 采用注释

  1. @MappedTypes(List.class)
  2. @MappedJdbcTypes({JdbcType.VARCHAR})
  3. public class MyListTypeHandler extends BaseTypeHandler<List<String>>{
  4. @Override
  5. public void setNonNullParameter(PreparedStatement ps, int i, List<String> parameter, JdbcType jdbcType)
  6. throws SQLException {
  7. if(parameter != null) {
  8. // List集合转字符串
  9. StringBuffer sbBuffer = new StringBuffer();
  10. for(String string : parameter) {
  11. sbBuffer.append(string).append(",");
  12. }
  13. ps.setString(i, sbBuffer.toString().substring(0,sbBuffer.toString().length()-1));
  14. }
  15. }
  16. @Override
  17. public List<String> getNullableResult(ResultSet rs, String columnName) throws SQLException {
  18. if(rs.getString(columnName) != null) {
  19. String[] split = rs.getString(columnName).split(",");
  20. return Arrays.asList(split);
  21. }
  22. return null;
  23. }
  24. @Override
  25. public List<String> getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
  26. String[] split = rs.getString(columnIndex).split(",");
  27. return Arrays.asList(split);
  28. }
  29. @Override
  30. public List<String> getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
  31. String[] split = cs.getString(columnIndex).split(",");
  32. return Arrays.asList(split);
  33. }
  34. }

3、 数据库 与 java model类

sex属性类型用自定义SexEnum 枚举类型

  1. public class User {
  2. private Integer id;
  3. private String username;
  4. private String pazzword;
  5. private Integer state;
  6. private Date regDate;
  7. private SexEnum sex; // 1:男, 0:女,用枚举
  8. private List<String> interest; //爱好
  9. ...}

20181123195809647.png

4、在sql映射文件中进行配置

注意: 获取数据和插入数据 的 配置

  1. <resultMap id="BaseResultMap" type="cn.jq.mybatis.model.User">
  2. <id column="id" jdbcType="INTEGER" property="id" />
  3. <result column="username" jdbcType="VARCHAR" property="username" />
  4. <result column="pazzword" jdbcType="VARCHAR" property="pazzword" />
  5. <result column="state" jdbcType="INTEGER" property="state" />
  6. <result column="reg_date" jdbcType="TIMESTAMP" property="regDate" />
  7. <result column="sex" property="sex"
  8. jdbcType="INTEGER"
  9. javaType="cn.jq.mybatis.enums.SexEnum"
  10. typeHandler="cn.jq.mybatis.enums.MySexTypeHandler"/>
  11. <result column="interest" property="interest"
  12. typeHandler="cn.jq.mybatis.enums.MyListTypeHandler"/>
  13. </resultMap>
  14. <sql id="Base_Column_List">
  15. id, username, pazzword, state, reg_date, sex, interest
  16. </sql>
  17. <select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">
  18. select
  19. <include refid="Base_Column_List" />
  20. from t_user
  21. where id = #{id,jdbcType=INTEGER}
  22. </select>
  23. <insert id="insertUser" >
  24. insert into t_user
  25. (username,pazzword,state,reg_date,sex,interest)
  26. values
  27. (#{username},#{pazzword},#{state},#{regDate},
  28. #{sex, jdbcType=INTEGER, javaType=cn.jq.mybatis.enums.SexEnum, typeHandler=cn.jq.mybatis.enums.MySexTypeHandler},
  29. #{interest, typeHandler=cn.jq.mybatis.enums.MyListTypeHandler})
  30. </insert>

5、在全局配置文件中注册自定义的typeHandler

  1. 注意标签配置顺序: set 标签之后
  2. <typeHandlers>
  3. <typeHandler handler="cn.jq.mybatis.enums.MyListTypeHandler" />
  4. <typeHandler handler="cn.jq.mybatis.enums.MySexTypeHandler" />
  5. </typeHandlers>

6、测试

1)insert数据

  1. UserMapper userMapper = session.getMapper(UserMapper.class);
  2. List<String> list = new ArrayList<String>();
  3. list.add("足球");
  4. list.add("排球");
  5. list.add("音乐");
  6. User user = new User();
  7. user.setUsername("ad22");
  8. user.setPazzword("pass22");
  9. user.setState(1);
  10. user.setRegDate(new Date());
  11. user.setSex(SexEnum.FMALE);
  12. //user.setInterest(null); //爱好为空,自定义typeHandle做了判断
  13. user.setInterest(list);
  14. userMapper.insertUser(user);
  15. session.commit();
  16. System.out.println(user);

20181123200736761.png

数据库:

20181123200810445.png

2)select 数据

  1. User user1 = userMapper.selectByPrimaryKey(1);
  2. System.out.println(user1);

20181123200536662.png

#

小结
OK,经过上面的介绍,想必小伙伴对typeHandler的使用已经有一定了解了,总结一下就是读取时的配置要和插入时的配置分开来做,

读取时数据转换我们有两种配置方式,分别是resultMap和在mybatis配置文件中配置typeHandlers,

插入时的配置就是在insert节点中进行配置。

参考文章:

https://blog.csdn.net/u012702547/article/details/54572679

https://www.cnblogs.com/dongying/p/4040435.html

发表评论

表情:
评论列表 (有 0 条评论,349人围观)

还没有评论,来说两句吧...

相关阅读

    相关 定义TypeHandler

    在大部分的场景下,MyBatis 的 typeHandler 就能应付一般的场景,但是有时候不够用。比如使用枚举的时候,枚举有特殊的转化规则,这个时候需要自定义 typeHan