上一篇梳理了Configuration初始化分析,今天继续typeHandlers部分。

数据库厂商标识

接上一篇文章分析,下一个解析的是databaseIdProvider节点,这个节点好理解,从字面理解就是数据库提供商的id,也就是mybatis需要访问的数据库是那种数据库。

我们都知道mybatis只是一个ORM框架,并不是针对具体的数据库,需要兼容多种数据库,所以mybatis可以根据不同的数据库厂商执行不同的语句,这种多厂商的支持是基于映射语句中的 databaseId 属性。

解析在配置文件中配置的源码如下图:

打开网易新闻 查看更多图片

可以看到最终是返回一个字符串给到configuration的databaseId属性,同时我们也可以自己实现一个DatabaseIdProvider,不过要先在别名配置里面配置好。

类型处理器

因为无论是 MyBatis 预处理语句(PreparedStatement)中设置参数时,还是从结果集中取出一个值时, 都需要jdbc的数据类型和Java数据类型进行相互转换,而类型处理器就是提供这个功能的,mybatis解析的源码如下图:

打开网易新闻 查看更多图片

typeHandlerElement(root.evalNode("typeHandlers"));是解析类型映射器代码,从typeHandlerElement方法可以知道类型解析器支持两个方法,与别名一样支持包扫描和具体类型。包扫描和别名差不多流程,都是找到对应包下面所有类,然后解析放到TypeHandlerRegistry类中。

从上图源码中可以看出要实现Java类型到jdbc类型的相互映射需要三个类:Java类型,JDBC类型,Handler。获取到这个对象后调用TypeHandlerRegistry的register方法注册到TypeHandlerRegistry中去,那么这几个对象的关系该是如何映射的呢?

TypeHandlerRegistry对象保存有Java类型和JDBC类型的对应关系,从上图中TypeHandlerRegistry源码可以看到几个重要属性就能明白mybatis是如何实现类型间的映射了。关键属性解释如下:

Map将数据从Jdbc类型转换成Java类型

> jdbcTypeHandlerMap:记录JdbcType和TypeHandler之间的对应关系,其中JdbcType是一个枚举类型,它定义对应的JDBC类型,该集合主要用于从结果集读取数据时,

Map所以存在一对多的关系,所以值要用Map来存储;

>> typeHandlerMap :记录了Java类型向指定的JdbcType转换时,需要使用的TypeHandler对象,因为一个Java类型可能对应多个数据库类型,比如Java类型中的String可能转换成数据库的char、varchar等多种类型,

TypeHandler unknownTypeHandler:一些未知类型对象的TypeHandler;

Map

, TypeHandler> allTypeHandlersMap:记录了全部TypeHandler的类型以及该类型相应的TypeHandler对象;

最关键是前面两个属性,jdbcTypeHandlerMap用于查询结果转Java时使用,typeHandlerMap 用于在Java类型转jdbc类型时使用。

在上图右侧的TypeHandlerRegistry源码中可以看到两个构造方法,会先把Configuration中一些类型映射生成unknownTypeHandler属性,然后对常见的类型映射进行了初始化。

类型处理器自定义

从上面的源码中可以得出要自定义一个类型处理器只需要实现TypeHandler接口就行,并实现它的4个方法,这里实现了一个处理List集合的处理器,源码如下图:

打开网易新闻 查看更多图片

这四个方法还是挺简单的,第一个方法是在保存操作是把List对象转换成字符串设置到保存sql语句中,后面三个方法是在查出数据后再转换成List

创建好了就是使用了,使用的关键代码如下图:

打开网易新闻 查看更多图片

首先在配置文件中配置创建的类型,然后在插入的sql那里指定字段的处理器,然后就可以插入了,可以看到保存到数据库的结果和查询出来的结果,基本满足要求了。

总结

数据库id我们一般很少自己配置,除非有特殊需求,这里主要讲了类型处理器,有时候还是可以用上的。

这里只是实现了集合映射到数据的处理器,有时候我们还可能使用到枚举到数据库的映射,有兴趣的同学可以去了解下,也是比较简单的。

Configuration的初始化还是最后一个mapper的加载了,本来想在这篇完结的,发现mapper的内容太多,下一篇来详细梳理下。

Java程序员日常学习笔记,如理解有误欢迎各位交流讨论!

打开网易新闻 查看更多图片