MyBatis配置之typeHandler类型处理器

typeHandler类型处理器作用

MyBatis在预处理语句(PreparedStatement)中设置一个参数时,或者从结果集(ResultSet)中取出一个值时,都会用注册了的typeHandler经行处理。

由于数据库可能来自于不同的厂商,不同的厂商设置的参数可能有所不同,同时数据库也可以自定义数据类型,typeHandler允许根据项目的需要自定义设置Java传递到数据库的参数中,或者从数据库读出数据,我们也需要进行特殊的处理,这些都可以在自定义的typeHandler中处理,尤其是在使用枚举的时候我们常常需要使用typeHandler进行转换。

typeHandler常用的配置为Java类型(javaType)、JDBC类型(jdbcType)。typeHandler的作用就是将参数从javaType转化为jdbcType,或者从数据库取出结果时把jdbcType转化为javaType。

typeHandler类型处理器用法

typeHandler和别名一样,分为MyBatis系统定义和用户自定义两种。一般来说,使用MyBatis系统定义就可以实现大部分功能。在本文中就不讲解MyBatis系统定义typeHandler用法,感兴趣的话,可以去看看org.apache.ibatis.type.TypeHandlerRegistry源码。

自定义typeHandler

自定义typeHandler前,首先需要明确两个问题:

  • 现有的typeHandler能否满足使用的要求?
  • 自定义的typeHandler需要处理什么类型【需特殊处理的Java类型(javaType)和对应处理数据库的类型jdbcType】?

第一步:注册自定义typehandler

<typeHandlers>
  <!--自定义typeHandler类-->
  <typeHandler jdbcType="VARCHAR" javaType="string" handler="com.demo.typeHandler.MyStringTypeHandler"/>
  <!--也可以使用扫描注册-->
  <package name="com.demo.typeHandler" />
</typeHandlers>

上述代码是配置在mybatis-config.xml配置文件中的。意味着通知系统,当Java的参数为string类型的时候,请使用自定义的MyStringTypeHandler类型处理器进行处理。

第二步:编写MyStringTypeHandler.java

@MappedType({String.class})
@MappedJdbcTypes(jdbgType.VARCHAR)
public class MyStringTypeHandler implements TypeHandler<String> {
  private Logger log = Logger.getLogger(MyStringTypeHandler.class);
  @Override
  public void setParameter(PreparedStatement ps,int index,String value,JdbcType jt) throws SQLException {
    log.info("使用自定义的TypeHandler")
    ps.setString(index,value);
  }
  @Override
  public String getResult(ResultSet rs,String colName) throws SQLException {
    log.info("使用自定义的TypeHandler,ResultSet列名获取字符串");
    return rs.getString(colName);
  }
  @Override
  public String getResult(ResultSet rs,int index) throws SQLException {
    log.info("使用自定义的TypeHandler,ResultSet下标获取字符串");
    return rs.getString(index);
  }
  @Override
  public String getResult(CallableStatement cs,int index) throws SQLException {
    log.info("使用自定义的TypeHandler,CallableStatement下标获取字符串");
    return cs.getString(index);
  }
}

自定义的TypeHandler里使用注解配置JdbcType和JavaType。

@MappedType定义的是JavaType类型,可以指定哪些Java类型被拦截;@MappedJdbcType定义的是JdbcType类型,它需要满足枚举类org.apache.ibatis.type.JdbcType所列的枚举类型;

第三步:修改映射文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="这里填写mapper类的【实体类】的全路径限定名,列如com.demp.mapper.RoleMapper">
  <resultMap type="role" id="roleMap">
    <!--定义结果类型转化器标识,才能使用类型转换器-->
    <id column="id" property="id" javaType="long" jdbcType="BIGINT" />
    <result column="role_name" property="roleName" javaType="string" jdbcType="VARCHAR" />
    <result column="note" property="note" typeHandler="com.demo.typeHandler.MyStringTypeHandler" />
  </resultMap>
  <select id="getRole" parameterType="long" resultMap="roleMap">
    select id,role_name,note from t_role where id=#{id}
  </select>
  <select id="findRole" parameterType="string" resultMap="roleMap">
    select id,role_name,note from t_role where role_name like concat('%',#{roleName javaType=string,jdbcType=VARCHAR,typeHandler=com.demo.typeHandler.MyStringTypeHandler},'%')
  </select>
  <insert id="insertRole" parameterType="role">
    insert into t_role(role_name,note) values (#{roleName}.#{note})
  </insert>
  <delete id="deleteRole" parameterType="long">
    delete from t_role where id=#{id}
  </delete>
</mapper>

配置文件中引入了resultMap,它提供了映射规则,给出了3种typeHandler的使用方法。

  • 在配置文件里配置,在结果集的roleName定义jdbcType和javaType。只有定义的jdbcType、javaType和用户自定义在配置里面的typeHandler是一致的,MyBatis才能够知道用自定义的类型转化器进行转换。
  • 映射集里面直接定义具体的typeHandler,这样就不需要再在配置里面定义了。
  • 在参数中制定typeHandler,这样MyBatis就会用对应的typeHandler进行转换。这样也不需要在配置里面定义了。

原创文章,作者:ZERO,如若转载,请注明出处:https://www.edu24.cn/course/mybatis-typehandler.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
ZEROZERO
上一篇 2022年4月18日
下一篇 2022年4月21日

相关推荐

  • 一维数组结构数据转换树形结构数据JS方法

    在写小程序项目时,自定义了一个组织机构树形展示组件,后端接口返回的组织机构数据是一维数组。需要在前端转换成树形结构的数据,并且添加一些节点的树形,比如是否为叶子节点,节点是否展开等…

    2022年11月10日
    533
  • css布局基础总结

    前端css布局知识繁杂,实现方式多种多样。想写出高效、合理的布局,必须以深厚的css基础为前提。为了方便记忆和复习,将css布局要点记录如下。内容较多,应用方面说的不太详细,但都是…

    2018年9月13日
    2.4K
  • Java自学之泛型

    在Java语言中,为了方便接收参数类型的统一,提供了核心类Object,利用此类对象可以接收所有类型的数据(包括基本数据类型和引用数据类型)。但是由于其所描述的数据范围过大,所以在…

    2020年12月8日
    1.4K
  • 曾被问及的一些关于VUE的面试题

    由于没有系统的专研过VUE,关于VUE的一些理论知识点,没有去挖心思记忆及理解,只是在实际工作中知道怎么去使用。所以曾在面试的过程中被人嫌弃过,这一直是小编的痛点,/(ㄒoㄒ)/~…

    2022年4月2日
    896
  • Webpack入门,自定义loader

    有时开发者会遇到现有loader无法很好满足需求的情况,这时就需要对其进行修改,或者编写新的loader。 下面以一个简单的示例,讲解以下如何实现一个loader。 需求 实现一个…

    2022年11月23日
    830
  • Webpack入门,模块打包之CommonJS简介

    CommonJS 说到前端的模块,不得不讲一下CommonJS。CommonJS是由JavaScript社区于2009年提出的包含模块、文件、IO、控制台在内的一系列标准。Node…

    2022年11月10日
    619
  • spring boot练习篇之用户登录系统【接口篇】

    写在前面 抛弃JSP,只做纯粹的前后端分离项目。 作为一个资深前端工作者,想要转JavaWeb开发,无论是书籍,还是网上视频、资料,竟然没有一篇能清楚明白地讲解怎样搭建一个前后端分…

    2021年5月25日
    1.7K
  • 深入理解JS内存机制

    JS的内存机制在很多前端开发者看来并不是那么重要,但是如果你想深入学习JS,并将它利用好,打造高质量高性能的前端应用,就必须要了解JS的内存机制。对于内存机制理解了以后,一些基本的…

    2019年7月14日
    1.8K
  • 函数防抖与函数节流

    函数防抖 定义 触发高频事件后 n 秒内函数只会执行一次,如果 n 秒内高频事件再次被触发,则重新计算时间;更直白一点就是:一个需要频繁触发的函数,在规定时间内,只让最后一次生效,…

    2020年7月17日
    1.5K
  • Java自学之类与对象

    定义 类是由成员属性和方法组成。成员属性主要定义类的一个具体信息,实际上一个成员属性就是一个变量,而方法是一些操作的行为。类的定义基础语法如下。 一个类定义完成后并不能够被直接使用…

    2020年11月25日
    1.4K