我是靠谱客的博主 香蕉洋葱,最近开发中收集的这篇文章主要介绍mybatis--自定义typeHandler的使用,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

场景:

        在做开发时,我们经常会遇到这样一些问题,比如我有一个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的使用所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(49)

评论列表共有 0 条评论

立即
投稿
返回
顶部