博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Ibatis的类型处理器TypeHandler解析
阅读量:6985 次
发布时间:2019-06-27

本文共 4868 字,大约阅读时间需要 16 分钟。

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

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

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

......
......

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

  例如这里的全局配置,如果此时某个数据库字段的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) { // 注意这里,如果配置了就使用这个配置的handler            Object 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) {      // Unknown      handler = typeHandlerFactory.getUnkownTypeHandler();    } else if (DomTypeMarker.class.isAssignableFrom(clazz)) {      // DOM      handler = typeHandlerFactory.getTypeHandler(String.class, jdbcType);    } else if (java.util.Map.class.isAssignableFrom(clazz)) {      // Map      if (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) {      // Primitive      handler = typeHandlerFactory.getTypeHandler(clazz, jdbcType);    } else {      // JavaBean      if (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 。

转载地址:http://ddqpl.baihongyu.com/

你可能感兴趣的文章
Codeforces 606-C:Sorting Railway Cars(LIS)
查看>>
eclipse ldt update resource
查看>>
java-HTML&javaSkcript&CSS&jQuery&ajax
查看>>
RESTful API 设计最佳实践
查看>>
移动端自动化==>什么是Appium
查看>>
antd递归渲染左侧菜单
查看>>
IP通信基础第二周
查看>>
BZOJ 4070 [Apio2015]雅加达的摩天楼 ——分块 SPFA
查看>>
经典最小二乘法
查看>>
Vue.js安装
查看>>
XNA 游戏 运行时编辑器
查看>>
.Net Core建站(1):EF Core+CodeFirst数据库生成
查看>>
UVA 12672 Eleven(DP)
查看>>
LINQ之路系列博客后记
查看>>
Python的单例模式
查看>>
初识Redis
查看>>
ajax初试,获取数据
查看>>
Java GC垃圾回收机制
查看>>
判断JavaScript对象为null或者属性为空
查看>>
数组---进制转换(查表法)
查看>>