Mybatis 生成SQL时自动获取 TypeHandler

在介绍了Mybatis是如何注册TypeHandler之后就介绍一下Mybatis是如何获取对应的TypeHandler进行类型转换的。

  1. 如果我们在Mapper.xml文件中配置某一个属性或变量的映射关系时,指定了该属性对应的javaType和jdbcType;
  2. 则Mybatis会从注册好的TypeHandler中寻找对应的javaType和jdbcType组合的TypeHandler进行处理;
  3. 这也是Mybatis最基本的获取TypeHandler进行类型转换的方式。

一、较为完整的MyBatis 中typeHandler配置

假设Mybatis配置文件中有这么一段TypeHandler的注册信息:

<typeHandlers>  
   <typeHandler handler="com.tiantian.mybatis.handler.StringArrayTypeHandler" javaType="[Ljava.lang.String;" jdbcType="VARCHAR"/>  
</typeHandlers>

看这样一个UserMapper.xml定义:

<?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="com.tiantian.mybatis.mapper.UserMapper">  
    <resultMap id="UserResult" type="User">  
       <id column="id" property="id"/>  
       <result column="interests" property="interests" javaType="[Ljava.lang.String;" jdbcType="VARCHAR"/>  
    </resultMap>  
   
    <insert id="insertUser" parameterType="User" useGeneratedKeys="true" keyColumn="id">  
       insert into t_user(name, age, interests) values(#{name}, #{age}, #{interests, javaType=[Ljava.lang.String;, jdbcType=VARCHAR})  
    </insert>  
     
    <update id="updateUser" parameterType="User">  
       update t_user set name=#{name}, age=#{age}, interests=#{interests} where id=#{id}  
    </update>  
     
    <select id="findById" parameterType="int" resultMap="UserResult">  
       select * from t_user where id=#{id}  
    </select>  
     
    <delete id="deleteUser" parameterType="int">  
       delete from t_user where id=#{id}  
    </delete>  
</mapper>

1.1、配置说明

我们可以看到在id为UserResult的resultMap中,

  • 我们定义了一个对应字段interests的映射关系,并且定义了其javaType为“[Ljava.lang.String;”,jdbcType为VARCHAR,
  • 这个时候Mybatis就会到已经注册了的TypeHandler中寻找到能处理javaType和jdbcType对应的类型转换的TypeHandler来进行处理。
  • 在这里就会找到我们注册的StringArrayTypeHandler。

在上面id为insertUser的insert语句中,

  • 我们也为变量interests指定了它的javaType和jdbcType属性,这时候Mybatis也会寻找javaType和jdbcType对应的TypeHandler。

上面这样定义是Mybatis最基本也是最完整地获取到对应的TypeHandler的方法。

1.2、代码使用测试

这里我们来对UserMapper(它的代码我就不贴出来了,有Mybatis基础的都应该知道它的代码)的findById来做一个测试:

@Test  
public void testFind() {  
   SqlSession sqlSession = sqlSessionFactory.openSession();  
   try {  
       UserMapper userMapper = sqlSession.getMapper(UserMapper.class);  
       User user = userMapper.findById(20);  
       System.out.println(user);  
   } finally {  
       sqlSession.close();  
   }  
}

其输出结果如下:

User [age=30, id=20, interests=[Music, Movie, NBA], name=张三]

我们可以看到Mybatis已经把我们存放在数据库中VARCHAR类型的字段interests转换为User类字符串数组类型的interests属性,这说明我们定义的StringArrayTypeHandler发生作用了。

除了上面的完整指定一个变量对应的javaType和jdbcType,让Mybatis能够完美的找到对应的TypeHandler之外。我们平时书写配置的时候,可能会少写部分配置。

二、只指定变量对应的javaType类型

这个时候Mybatis会拿着这个javaType和jdbcType为null的组合到注册的TypeHandler中寻找对应的TypeHandler。

2.1、测试一:TypeHandler 注册的 jdbcType 不为NULL

不动StringArrayTypeHandler的注册信息,把我们的UserMapper.xml改为如下形式:

<?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="com.tiantian.mybatis.mapper.UserMapper">  
    <resultMap id="UserResult" type="User">  
       <id column="id" property="id"/>  
       <result column="interests" property="interests" javaType="[Ljava.lang.String;"/>  
    </resultMap>  
    <select id="findById" parameterType="int" resultMap="UserResult">  
       select * from t_user where id=#{id}  
    </select>  
</mapper>

这时候再运行上面的测试程序,输出结果如下:

User [age=30, id=20, interests=null, name=张三]

我们可以看到输出的interests为null,这说明Mybatis没有使用我们定义的StringArrayTypeHandler来转换interests。

2.2、测试二:TypeHandler 注册的 jdbcType 为null

UserMapper.xml还像上面那样定义,但是也只指定javaType属性来注册我们的StringArrayTypeHandler,代码如下:

<?xml version="1.0" encoding="UTF-8" ?>  
<!DOCTYPE configuration  
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"  
  "http://mybatis.org/dtd/mybatis-3-config.dtd">  
<configuration>  
    <properties resource="config/jdbc.properties"></properties>  
    <typeAliases>  
       <package name="com.tiantian.mybatis.model"/>  
    </typeAliases>  
    <typeHandlers>  
       <typeHandler handler="com.tiantian.mybatis.handler.StringArrayTypeHandler" javaType="[Ljava.lang.String;"/>  
    </typeHandlers>  
...........
    <mappers>  
       <mapper resource="com/tiantian/mybatis/mapper/UserMapper.xml"/>  
    </mappers>  
</configuration>

这个时候再运行上面的测试代码,输出结果如下:

User [age=30, id=20, interests=[Music, Movie, NBA], name=张三]

这是因为我们是以javaType和null注册的StringArrayTypeHandler,然后在需要转换interests时又是以相同的javaType和null来寻找的,所以就会找到我们注册的StringArrayTypeHandler来进行类型转换。

三、只指定变量对应的jdbcType类型

这个时候Mybatis会利用我们指定的返回类型和对应的属性,取该属性在返回类型中对应的javaType,之后再拿着该javaType和我们指定的jdbcType到注册的TypeHandler中获取对应的TypeHandler。

3.1、测试一:根据返回值类型分析 javaType

保持之前指定javaType和jdbcType的方式注册StringArrayTypeHandler,然后在定义interests变量的时候不指定javaType,只指定jdbcType。

这个时候UserMapper.xml如下所示:

<?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="com.tiantian.mybatis.mapper.UserMapper">  
    <resultMap id="UserResult" type="User">  
       <id column="id" property="id"/>  
       <result column="interests" property="interests" jdbcType="VARCHAR"/>  
    </resultMap>  
    <select id="findById" parameterType="int" resultMap="UserResult">  
       select * from t_user where id=#{id}  
    </select>  
</mapper>

这个时候继续运行上面的测试代码,输出结果如下:

User [age=30, id=20, interests=[Music, Movie, NBA], name=张三]

这个时候Mybatis是这样获取TypeHandler的:

  • 首先它发现我们的interests没有指定javaType;
  • 这个时候它就会通过我们指定的类型User和属性interests获取User类的interests属性对应的java类型,即String数组;
  • 再拿着获取到的javaType和我们指定的jdbcType即VARCHAR去寻找对应的TypeHandler,
  • 这个时候就找到了我们之前以String数组和VARCHAR注册好的StringArrayTypeHandler来处理interests的类型转换。

四、javaType类型和jdbcType类型都不指定

这个时候Mybatis会以第三小节中的方式(三、只指定变量对应的jdbcType类型)获取到对应的javaType类型,然后再以第二小节的方式(只指定变量对应的javaType类型)获取到对应的TypeHandler。

五、直接在Mapper文件中通过 typeHandler 属性指明 typeHandler

这个时候Mybatis就会使用该用户自己指定的TypeHandler来进行类型转换,而不再以javaType和jdbcType组合的方式获取对应的TypeHandler。

5.1、配置示例

<?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="com.tiantian.mybatis.mapper.UserMapper">  
    <resultMap id="UserResult" type="User">  
       <id column="id" property="id"/>  
       <result column="interests" property="interests" typeHandler="com.tiantian.mybatis.handler.StringArrayTypeHandler"/>  
    </resultMap>  
    <select id="findById" parameterType="int" resultMap="UserResult">  
       select * from t_user where id=#{id}  
    </select>  
</mapper>

运行上面的测试代码,输出结果:

User [age=30, id=20, interests=[Music, Movie, NBA], name=张三]

这是因为我们指定了进行interests字段的映射关系时使用StringArrayTypeHandler来进行类型转换。

当指定了某一个字段或变量进行映射关系时所使用的TypeHandler时,Mybatis在需要进行类型转换时就使用给定的TypeHandler进行类型转换,而不会再通过javaType和jdbcType的组合去注册好的TypeHandler中寻找对应的TypeHandler。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值