首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 其他教程 > 开源软件 >

Ibatis的部类处理器TypeHandler解析

2012-06-28 
Ibatis的类型处理器TypeHandler解析原文来自: http://blog.csdn.net/lovingprince/article/details/276884

Ibatis的类型处理器TypeHandler解析

原文来自: http://blog.csdn.net/lovingprince/article/details/2768849

?

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

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

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

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

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

    <typeHandlers>
  1. <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中取出配置属性。

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

?

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

?

    public?TypeHandler?resolveTypeHandler(TypeHandlerFactory?typeHandlerFactory,?Class?clazz,?String?propertyName,?String?javaType,?String?jdbcType,?boolean?useSetterToResolve)?{
  1. ????TypeHandler?handler?=?null; ????if?(clazz?==?null)?{
  2. ??????//?Unknown ??????handler?=?typeHandlerFactory.getUnkownTypeHandler();
  3. ????}?else?if?(DomTypeMarker.class.isAssignableFrom(clazz))?{ ??????//?DOM
  4. ??????handler?=?typeHandlerFactory.getTypeHandler(String.class,?jdbcType); ????}?else?if?(java.util.Map.class.isAssignableFrom(clazz))?{
  5. ??????//?Map ??????if?(javaType?==?null)?{
  6. ????????handler?=?typeHandlerFactory.getUnkownTypeHandler();?//BUG?1012591?-?typeHandlerFactory.getTypeHandler(java.lang.Object.class,?jdbcType); ??????}?else?{
  7. ????????try?{ ??????????Class?javaClass?=?Resources.classForName(javaType);
  8. ??????????handler?=?typeHandlerFactory.getTypeHandler(javaClass,?jdbcType); ????????}?catch?(Exception?e)?{
  9. ??????????throw?new?NestedRuntimeException("Error.??Could?not?set?TypeHandler.??Cause:?"?+?e,?e); ????????}
  10. ??????} ????}?else?if?(typeHandlerFactory.getTypeHandler(clazz,?jdbcType)?!=?null)?{
  11. ??????//?Primitive ??????handler?=?typeHandlerFactory.getTypeHandler(clazz,?jdbcType);
  12. ????}?else?{ ??????//?JavaBean
  13. ??????if?(javaType?==?null)?{ ????????if?(useSetterToResolve)?{
  14. ??????????Class?type?=?PROBE.getPropertyTypeForSetter(clazz,?propertyName); ??????????handler?=?typeHandlerFactory.getTypeHandler(type,?jdbcType);
  15. ????????}?else?{ ??????????Class?type?=?PROBE.getPropertyTypeForGetter(clazz,?propertyName);
  16. ??????????handler?=?typeHandlerFactory.getTypeHandler(type,?jdbcType); ????????}
  17. ??????}?else?{ ????????try?{
  18. ??????????Class?javaClass?=?Resources.classForName(javaType); ??????????handler?=?typeHandlerFactory.getTypeHandler(javaClass,?jdbcType);
  19. ????????}?catch?(Exception?e)?{ ??????????throw?new?NestedRuntimeException("Error.??Could?not?set?TypeHandler.??Cause:?"?+?e,?e);
  20. ????????} ??????}
  21. ????} ????return?handler;
  22. ??}
  23. 相信大家已经很明白了,其实要找一个Handler,主要就是需要javaType和jdbcType,而这两个参数要么通过反射得到,要么通过配置文件中得到。因此,为了明确我们一般都在配置文件中进行申明。
  24. 最后来看一点 typeHandlerFactory.getTypeHandler(clazz,?jdbcType)是怎么实现的。
    1. ??public?TypeHandler?getTypeHandler(Class?type,?String?jdbcType)?{
    2. ????Map?jdbcHandlerMap?=?(Map)?typeHandlerMap.get(type);//首先根据JAVA类型 ????TypeHandler?handler?=?null;
    3. ????if?(jdbcHandlerMap?!=?null)?{ ??????handler?=?(TypeHandler)?jdbcHandlerMap.get(jdbcType);//每个JDBC类型
    4. ??????if?(handler?==?null)?{ ????????handler?=?(TypeHandler)?jdbcHandlerMap.get(null);
    5. ??????} ????}
    6. ????return?handler; ??}
  25. 其实一个Handler=javaType+jdbcType 。

热点排行