Ibatis的类型处理器TypeHandler解析

【微服务】mybatis typehandler使用详解 mybatis typehandler 使用详解 阅读详情

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

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

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

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

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

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

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

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

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

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

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

  1.       String propertyName = childAttributes.getProperty("property");
  2.         String nullValue = childAttributes.getProperty("nullValue");
  3.         String jdbcType = childAttributes.getProperty("jdbcType");
  4.         String javaType = childAttributes.getProperty("javaType");
  5.         String columnName = childAttributes.getProperty("column");
  6.         String columnIndex = childAttributes.getProperty("columnIndex");
  7.         String statementName = childAttributes.getProperty("select");
  8.         String resultMapName = childAttributes.getProperty("resultMap");
  9.         String callback = childAttributes.getProperty("typeHandler");
  10.         callback = vars.typeHandlerFactory.resolveAlias(callback);
  11.         javaType = vars.typeHandlerFactory.resolveAlias(javaType);
  12.         TypeHandler handler = null;
  13.         if (callback != null) { // 注意这里,如果配置了就使用这个配置的handler
  14.             Object impl = Resources.classForName(callback).newInstance();
  15.             if (impl instanceof TypeHandlerCallback) {
  16.               handler = new CustomTypeHandler((TypeHandlerCallback) impl);
  17.             } else if (impl instanceof TypeHandler) {
  18.               handler = (TypeHandler) impl;
  19.             } else {
  20.               throw new NestedRuntimeException ("The class '' is not a valid implementation of TypeHandler or TypeHandlerCallback");
  21.             }
  22.         } else {//如果没有配置,就到这里来找
  23.                   handler = resolveTypeHandler(vars.client.getDelegate().getTypeHandlerFactory(), vars.currentResultMap.getResultClass(), propertyName, javaType, jdbcType, true);
  24.         }

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

  1. public TypeHandler resolveTypeHandler(TypeHandlerFactory typeHandlerFactory, Class clazz, String propertyName, String javaType, String jdbcType, boolean useSetterToResolve) {
  2.     TypeHandler handler = null;
  3.     if (clazz == null) {
  4.       // Unknown
  5.       handler = typeHandlerFactory.getUnkownTypeHandler();
  6.     } else if (DomTypeMarker.class.isAssignableFrom(clazz)) {
  7.       // DOM
  8.       handler = typeHandlerFactory.getTypeHandler(String.class, jdbcType);
  9.     } else if (java.util.Map.class.isAssignableFrom(clazz)) {
  10.       // Map
  11.       if (javaType == null) {
  12.         handler = typeHandlerFactory.getUnkownTypeHandler(); //BUG 1012591 - typeHandlerFactory.getTypeHandler(java.lang.Object.class, jdbcType);
  13.       } else {
  14.         try {
  15.           Class javaClass = Resources.classForName(javaType);
  16.           handler = typeHandlerFactory.getTypeHandler(javaClass, jdbcType);
  17.         } catch (Exception e) {
  18.           throw new NestedRuntimeException("Error.  Could not set TypeHandler.  Cause: " + e, e);
  19.         }
  20.       }
  21.     } else if (typeHandlerFactory.getTypeHandler(clazz, jdbcType) != null) {
  22.       // Primitive
  23.       handler = typeHandlerFactory.getTypeHandler(clazz, jdbcType);
  24.     } else {
  25.       // JavaBean
  26.       if (javaType == null) {
  27.         if (useSetterToResolve) {
  28.           Class type = PROBE.getPropertyTypeForSetter(clazz, propertyName);
  29.           handler = typeHandlerFactory.getTypeHandler(type, jdbcType);
  30.         } else {
  31.           Class type = PROBE.getPropertyTypeForGetter(clazz, propertyName);
  32.           handler = typeHandlerFactory.getTypeHandler(type, jdbcType);
  33.         }
  34.       } else {
  35.         try {
  36.           Class javaClass = Resources.classForName(javaType);
  37.           handler = typeHandlerFactory.getTypeHandler(javaClass, jdbcType);
  38.         } catch (Exception e) {
  39.           throw new NestedRuntimeException("Error.  Could not set TypeHandler.  Cause: " + e, e);
  40.         }
  41.       }
  42.     }
  43.     return handler;
  44.   }
  45. 相信大家已经很明白了,其实要找一个Handler,主要就是需要javaType和jdbcType,而这两个参数要么通过反射得到,要么通过配置文件中得到。因此,为了明确我们一般都在配置文件中进行申明。
  46. 最后来看一点 typeHandlerFactory.getTypeHandler(clazz, jdbcType)是怎么实现的。
    1.   public TypeHandler getTypeHandler(Class type, String jdbcType) {
    2.     Map jdbcHandlerMap = (Map) typeHandlerMap.get(type);//首先根据JAVA类型
    3.     TypeHandler handler = null;
    4.     if (jdbcHandlerMap != null) {
    5.       handler = (TypeHandler) jdbcHandlerMap.get(jdbcType);//每个JDBC类型
    6.       if (handler == null) {
    7.         handler = (TypeHandler) jdbcHandlerMap.get(null);
    8.       }
    9.     }
    10.     return handler;
    11.   }
  47. 其实一个Handler=javaType+jdbcType 。
使用iBatis类型处理器TypeHandlerCallback NULL 博文链接:https://wangym.iteye.com/blog/1439520 立即下载

相关推荐

Mybatis之TypeHandler入门:深入解析与实战技巧

TypeHandler是Mybatis中用于处理Java类型和SQL类型的转换器。当执行SQL语句时,Mybatis会将Java对象中的属性值转换为SQL语句中需要的类型;而查询结果返回时,TypeHandler则负责将数据库中的数据转换回相应的Java类型TypeHandler的存在使得Mybatis能够轻松应对各种复杂的数据类型转换需求。对于一些复杂的数据类型,如日期、枚举或自定义类,我们通常需要自定义TypeHandler。// 自定义DateTypeHandler类@Override。

一个做过前端开发的产品经理,经历过睿智产品的折磨导致脱发之后,励志要翻身"农奴"把歌唱,一边打入敌人内部一边持续提升自己,为我们广大开发同胞谋福祉,坚决抵制睿智产品折磨我们码农兄弟! 2685

MyBatis TypeHandler 实战指南:自定义类型转换与案例解析

Mybatis TypeHandler介绍使用举例,主要回顾Mybatis的原理内容,在介绍TypeHandler的基本功能,最后给出使用TypeHandler的样例和注意事项等内容

曾经“等你生日那天”都遥远得像未来,如今却可欢愉的挥手说“下个十年见” 86万+

IbatisTypeHandler

我们有一个Foo类,如下: class Foo { private int number; private String name; // getter、setter省略 } 有一张BIG_FOO表,如下: 列名 类型 ID BIGINT FOO VARCHAR 我们要把Foo类应射成BIG_FOO的FOO字段。也就是说,我们要

leeyang321的专栏 844

MyBatis自定义类型处理器 TypeHandler

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

lmb55的专栏 5万+

【MyBatis】源码学习 03 - 类型处理器 TypeHandler

第8章 type包 学习笔记。

MichelleChung的星球 855

MyBatis官方教程及源码解析——类型别名、类型处理器解析

MyBatis官方教程及源码解析——类型别名、类型处理器解析

orzxxx01的专栏 2088

IBATIS typeHandler 探究

我们可以在IBATIS中加入我们自定义类的支持。   IBATIS 提供给了我们两个 接口:   1,TypeHandlerCallback (一般我们扩展这个接口,说实话它和TypeHandler有什么非常大的区别我还没看出来,希望有人能帮我解答 )   2,TypeHandler     这里我研究了 TypeHandlerCallback 写了下代码:   承接上一篇...

平衡 trade-off 194

MyBatis-Plus13:自定义 TypeHandler

/ 存数据库时:明文 → 加密 → 存密文@Override// 取数据库时:密文 → 解密 → 返回明文(按列名)@Override// 取数据库时:密文 → 解密 → 返回明文(按列下标)@Override// 存储过程@Override因为这个需求是在 Java 和数据库之间做了额外的业务处理(加解密),不是简单的类型转换,任何内置的 TypeHandler 都做不到,只能自己写。

qq_31532983的博客 868
上一篇: ORA-01795异常的原因以及解决办法
下一篇: JAVA正则表达式高级用法(分组与捕获)
lovingprince
博客等级 码龄20年 907粉丝 177原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值