Mybatis 生成SQL时自动获取 TypeHandler
在介绍了Mybatis是如何注册TypeHandler之后就介绍一下Mybatis是如何获取对应的TypeHandler进行类型转换的。
如果我们在Mapper.xml文件中配置某一个属性或变量的映射关系时,指定了该属性对应的javaType和jdbcType;
则Mybatis会从注册好的TypeHandler中寻找对应的javaType和jdbcType组合的TypeHandler进行处理;
这也是Mybatis最基本的获取TypeHandler进行类型转换的方式。
一、较为完整的MyBatis 中typeHandler配置
假设Mybatis配置文件中有这么一段TypeHandler的注册信息:
看这样一个UserMapper.xml定义:
<?xml version="1.0" encoding="UTF-8" ?>insert into t_user(name, age, interests) values(#{name}, #{age}, #{interests, javaType=[Ljava.lang.String;, jdbcType=VARCHAR})update t_user set name=#{name}, age=#{age}, interests=#{interests} where id=#{id}select * from t_user where id=#{id}delete from t_user where id=#{id}
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来做一个测试:
@TestpublicvoidtestFind(){ 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" ?>select * from t_user where id=#{id}
这时候再运行上面的测试程序,输出结果如下:
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" ?>...........
这个时候再运行上面的测试代码,输出结果如下:
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" ?>select * from t_user where id=#{id}
这个时候继续运行上面的测试代码,输出结果如下:
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" ?>select * from t_user where id=#{id}
运行上面的测试代码,输出结果:
User [age=30, id=20, interests=[Music, Movie, NBA], name=张三]
这是因为我们指定了进行interests字段的映射关系时使用StringArrayTypeHandler来进行类型转换。
当指定了某一个字段或变量进行映射关系时所使用的TypeHandler时,Mybatis在需要进行类型转换时就使用给定的TypeHandler进行类型转换,而不会再通过javaType和jdbcType的组合去注册好的TypeHandler中寻找对应的TypeHandler。