欢迎访问昆山宝鼎软件有限公司网站! 设为首页 | 网站地图 | XML | RSS订阅 | 宝鼎邮箱 | 宝鼎售后问题提交 | 后台管理


新闻资讯

MENU

软件开发知识

[Mybatis] TypeHandler 的简朴应用及源码阐明

点击: 次  来源:宝鼎软件 时间:2017-07-14

原文出处: 开源中国

TypeHandlers

无论是 MyBatis 在预处理语句(PreparedStatement)中设置一个参数时,还是从结果集中取出一个值时,软件开发, 都会用类型处理器将获取的值以合适的方式转换成 Java 类型。

下面是常见的一些对应类型:

以BigDecimalTypeHandler看一下,它主要完成了哪些工作。

这个类的第一个方法是对预处理语句(PreparedStatement)设置参数,之后的三个函数都是从ResultSet或者用于执行存储过程的CallableStatement语句中获取BigDecimal类型的数值,用于向BigDecimal类型的Java字段赋值。 BigDecimalTypeHandler继承的BaseTypeHandler是个泛型类,其他的TypeHandler也是通过继承这个抽象类,实现其中的抽象方法,实现类型转换的工作。

这个抽象类实现了TypeHandler接口,这个接口主要定义了类型转换的几种操作。

至于这个抽象类继承的TypeReference<T>,主要是提供了获取这个T具体是哪个类型。在判断使用使用哪个TypeHandler时有用,后文会看到。 输入图片说明

如何使用

大致介绍了TypeHandler的作用,及其相关类,我们来看看如何使用它。 今天遇到的主要是从SqlServer中取数据,遇到很多列都是Numeric(10,2)类型,指的是字段是数字型,长度为10,小数为两位。Mybatis默认的BigDecimalTypeHandler取到后,都默认变成4位小数,不够的补了0。而上层的要求是,拿到的和数字相关的数据都要2位小数。

有两种做法,一种是在所有给上层赋值的时候,都人工对BigDeciam的数据做如下操作。

setScale(2, BigDecimal.ROUND_HALF_UP)

因为这是一个全局性的要求,所有相关的地方,都需要有这个代码,虽然可以写一个工具类,各个地方调用,但就对原本间接的代码造成了侵入。既然这样,为什么不试试TypeHandler。

我的做法是继承BigDecimalTypeHandler,覆盖原来的取值方法,对取到的数值做范围限定。

加上@MappedJdbcTypes注解是为了表明这个类是用于映射JdbcType的NUMERIC类型,这会覆盖默认的用于转换Java BegDecimal和Jdbc NUMERIC的BigDecimal,在后面源码中可略窥一二。

开发完这个转换类后,你需要在Mybatis的配置文件中声明这个TypeHandler,这样Mybatis才知道你自己声明了一个TypeHandler。

<typeHandlers>
    <typeHandler handler="com.codelab.learn.SubBigDecimalTypeHandler"/>
</typeHandlers>

这样TypeHandler就起作用了。下面是前后效果。

源码层面

首先Mybatis有一个默认的TypeHandler实现,这些TypeHandler是如何被Mybatis识别的呢。 答案是TypeHandlerRegistry。在Mybatis初始化配置的时候,TypeHandlerRegistry会把JdbcType和Java类型对应的映射关系注册进该类内部的Map中。

JDBC_TYPE_HANDLER_MAP中记录的是JdbcType和TypeHandler对应的关系。

TYPE_HANDLER_MAP中记录的是Java类型和对应的所有JdbcType以及其对应TypeHandler的映射关系关系。

 UNKNOWN_TYPE_HANDLER是在执行BaseTypeHandler的抽象方法时,去先解析出来该用什么TypeHandler,目前还没用到,先不研究。 ALL_TYPE_HANDLERS_MAP中记录的是所有TypeHandler的Class和其实例之间的映射关系。