Ibatis允许用户像在hibernate中一样定义自己的类型,但是,用户自定义类型需要与数据库中的字段类型进行对应。它的处理方法是允许我们扩展TypeHandler。Ibatis框架在处理该数据类型时就会自动调用TypeHandler进行类型转换,非常方便,ibatis中所有的类型都有它自己的TypeHandler,只是一些常用的数据类类型它已经给我们实现了而已。

  在配置文件中,我们有两个地方可以配置这种处理器。

  第一个地方是sqlMap文件中标签ResultMap或者ParameterMap中的TypeHandler属性,这里配置的handler是局部属性,只会在该ResultMap中才会进行转换。

<resultMap id="UserOrder" class="UserOrderDO" groupBy="id">......<result property="tripType" column="trip_Type"typeHandler="com.taobao.et.biz.dal.common.EnumTypeHandlerCallBack"/>......
</resultMap>

   第二个地方是sqlMapConfig文件中的标签typeHandlers中配置typeHandle子标签,这里配置的标签是全局属性,任何只要匹配该子标签的地方都会自动使用该Handler.

<typeHandlers>
<typeHandler jdbcType="CLOB" javaType="java.lang.String" callback="org.springframework.orm.ibatis.support.ClobStringTypeHandler"/>
</typeHandlers>

  例如这里的全局配置,如果此时某个数据库字段的jdbcType是CLOB类型,并且映射的JavaType类型是字符串类型,那么就会自动调用这里的callback来实行类型转换。

  那么Ibatis是如何确定使用哪一个TypeHandler的呢?!

它会在自己的局部区域寻找是否在配置文件中配置了Handler,找到了就使用这个handler,如果没有找到,就会查找是否有全局handler,也就是第二种方式配置的handler,这里要注意,可能我们也没有在全局配置文件中配置handler,此时,Ibatis就会根据实际类型配置默认的handler。

我们来看一些关键代码,按照查找步骤,这里我去掉了异常,只看关键的部分。

第一步:从局部Reultmap中取出配置属性。

     String propertyName = childAttributes.getProperty("property");String nullValue = childAttributes.getProperty("nullValue");String jdbcType = childAttributes.getProperty("jdbcType");String javaType = childAttributes.getProperty("javaType");String columnName = childAttributes.getProperty("column");String columnIndex = childAttributes.getProperty("columnIndex");String statementName = childAttributes.getProperty("select");String resultMapName = childAttributes.getProperty("resultMap");String callback = childAttributes.getProperty("typeHandler");callback = vars.typeHandlerFactory.resolveAlias(callback);javaType = vars.typeHandlerFactory.resolveAlias(javaType);TypeHandler handler = null;if (callback != null) { // 注意这里,如果配置了就使用这个配置的handlerObject impl = Resources.classForName(callback).newInstance();if (impl instanceof TypeHandlerCallback) {handler = new CustomTypeHandler((TypeHandlerCallback) impl);} else if (impl instanceof TypeHandler) {handler = (TypeHandler) impl;} else {throw new NestedRuntimeException ("The class '' is not a valid implementation of TypeHandler or TypeHandlerCallback");}} else {//如果没有配置,就到这里来找handler = resolveTypeHandler(vars.client.getDelegate().getTypeHandlerFactory(), vars.currentResultMap.getResultClass(), propertyName, javaType, jdbcType, true);}

  第二步,如果局部配置中没有找到,就到下面去找。

public TypeHandler resolveTypeHandler(TypeHandlerFactory typeHandlerFactory, Class clazz, String propertyName, String javaType, String jdbcType, boolean useSetterToResolve) {TypeHandler handler = null;if (clazz == null) {// Unknownhandler = typeHandlerFactory.getUnkownTypeHandler();} else if (DomTypeMarker.class.isAssignableFrom(clazz)) {// DOMhandler = typeHandlerFactory.getTypeHandler(String.class, jdbcType);} else if (java.util.Map.class.isAssignableFrom(clazz)) {// Mapif (javaType == null) {handler = typeHandlerFactory.getUnkownTypeHandler(); //BUG 1012591 - typeHandlerFactory.getTypeHandler(java.lang.Object.class, jdbcType);} else {try {Class javaClass = Resources.classForName(javaType);handler = typeHandlerFactory.getTypeHandler(javaClass, jdbcType);} catch (Exception e) {throw new NestedRuntimeException("Error.  Could not set TypeHandler.  Cause: " + e, e);}}} else if (typeHandlerFactory.getTypeHandler(clazz, jdbcType) != null) {// Primitivehandler = typeHandlerFactory.getTypeHandler(clazz, jdbcType);} else {// JavaBeanif (javaType == null) {if (useSetterToResolve) {Class type = PROBE.getPropertyTypeForSetter(clazz, propertyName);handler = typeHandlerFactory.getTypeHandler(type, jdbcType);} else {Class type = PROBE.getPropertyTypeForGetter(clazz, propertyName);handler = typeHandlerFactory.getTypeHandler(type, jdbcType);}} else {try {Class javaClass = Resources.classForName(javaType);handler = typeHandlerFactory.getTypeHandler(javaClass, jdbcType);} catch (Exception e) {throw new NestedRuntimeException("Error.  Could not set TypeHandler.  Cause: " + e, e);}}}return handler;}

  1. 相信大家已经很明白了,其实要找一个Handler,主要就是需要javaType和jdbcType,而这两个参数要么通过反射得到,要么通过配置文件中得到。因此,为了明确我们一般都在配置文件中进行申明。
  2. 最后来看一点 typeHandlerFactory.getTypeHandler(clazz, jdbcType)是怎么实现的。
public TypeHandler getTypeHandler(Class type, String jdbcType) {Map jdbcHandlerMap = (Map) typeHandlerMap.get(type);//首先根据JAVA类型TypeHandler handler = null;if (jdbcHandlerMap != null) {handler = (TypeHandler) jdbcHandlerMap.get(jdbcType);//每个JDBC类型if (handler == null) {handler = (TypeHandler) jdbcHandlerMap.get(null);}}return handler;}

  其实一个Handler=javaType+jdbcType 。

Ibatis的类型处理器TypeHandler解析相关推荐

  1. MyBatis自定义类型处理器 TypeHandler

    在项目开发中经常会遇到一个问题: 当我们在javabean中自定义了枚举类型或者其它某个类型,但是在数据库中存储时往往需要转换成数据库对应的类型,并且在从数据库中取出来时也需要将数据库类型转换为jav ...

  2. Mybatis——类型处理器TypeHandler

    在日常开发中使用mybatis时,mybatis的mapper.xml.mapper接口.entity实体一般会由mybatis-generator自动生成,其中实体的每个属性与数据库表的列一一对应, ...

  3. 【Mybatis】类型处理器TypeHandler的作用与自定义

    一.什么是类型处理器 1.类型处理器(TypeHandler) MyBatis 在设置预处理语句(PreparedStatement)中的参数或从结果集中取出一个值时,都会用类型处理器将获取到的值以合 ...

  4. 类型处理器TypeHandler

    作用:用于JavaType和JdbcType之间的转换 解析:当Mybatis将一个Java对象写入数据库时,它会创建一个PreparedStatument对象,并且使用setValue()方法对占位 ...

  5. MyBatis(九):MyBatis类型处理器(TypeHandler)详解

    TypeHandler简介 TypeHandler,顾名思义类型转换器,就是将数据库中的类型与Java中的类型进行相互转换的处理器. MyBatis 在设置预处理语句(PreparedStatemen ...

  6. MyBatis-Plus——字段类型处理器TypeHandler

    字段类型处理器(TypeHandler) 1,准备工作 (1)MyBatis 中的 TypeHandler 类型处理器用于 JavaType 与 JdbcType 之间的转换,假设我们用户表中有一个联 ...

  7. MyBatis核心源码剖析(SqlSession XML解析 Mapper executor SQL执行过程 自定义类型处理器 缓存 日志)

    MyBatis核心源码剖析 MyBatis核心源码剖析 1 MyBatis源码概述 1.1 为什么要看MyBatis框架的源码 1.2 如何深入学习MyBatis源码 1.3 源码分析的5大原则 2 ...

  8. mybatis TypeHandler 类型处理器

    目录 1. 自定义日期类型处理器 2. 配置自定义日期处理器 3. 新增,查询 1. 自定义日期类型处理器 继承mybatis提供的BaseTypeHandler覆写方法, 来转换Java和数据库中的 ...

  9. MyBatis自定义类型处理器(typeHandler)

    MyBatis自定义类型处理器(typeHandler) 我们执行sql语句通过PreparedStatement语句实现,PreparedStatement会设置?值,类型处理器帮PreparedS ...

最新文章

  1. php pdf 文字水印图片,php pdf添加水印(中文水印,图片水印)
  2. asp.net控件本质
  3. 005_Maven POM
  4. 基于PSO算法的带时间窗的车辆路径问题的仿真
  5. 6 redhat 查看rtc时间_Linux EasyStack-Redhat安装Docker
  6. 51单片机程序下载、ISP及串口基础知识
  7. 转:Python: threading.local是全局变量但是它的值却在当前调用它的线程当中
  8. parse 日期_日期parse()方法以及JavaScript中的示例
  9. Mysql 远程自动化备份
  10. 爬虫基本知识(转载)
  11. 常见的新算法的标准测试函数
  12. Qt学习(一)ui界面的设计
  13. css3动画: 3d照片旋转transfrom
  14. [ctf.show.reverse] 数学不及格
  15. 网站的工作原理:网络开发新手(或任何人)入门
  16. springboot下载网络图片到本地及Linux服务器(超详细)
  17. Java设计一个测桃花模块_20145209刘一阳《JAVA程序设计》第十五周补充测试
  18. 去水印小程序源码【2021年8月更新】
  19. 如何修改安卓日志缓冲区大小?
  20. APP在线抢答解决方案(RTC直播间抢答或者抢背唱歌)

热门文章

  1. Boost:Porthopper服务测试程序
  2. VTK:可视化之Legend
  3. VTK:Math之HomogeneousLeastSquares
  4. VTK:IO之ReadPLY
  5. VTK:IO之ReadBMP
  6. OpenCV使用VideoCapture界面读取一系列图像的实例(附完整代码)
  7. OpenGL 基础光照ColorsBasic Lighting
  8. C++ deque方法
  9. C++进程数量的限制
  10. QT的QShortcut类的使用