`

Ibatis的类型处理器TypeHandler解析

 
阅读更多

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

 

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

    4. 使用`@TypeHandler`注解:对于实体类的属性,可以直接在字段上使用`@TypeHandler`注解指定对应的类型处理器。 通过深入理解和灵活运用`TypeHandlerCallback`,开发者可以更好地控制数据在Java应用和数据库之间的...

    ibatis源码

    Ibatis的核心组件包括SqlMapConfig.xml配置文件、SqlSession管理、Executor执行器、Statement处理和TypeHandler类型处理器等。接下来,我们将详细探讨这些关键部分。 1. **SqlMapConfig.xml配置文件**:这是Ibatis...

    3、mybatis类型的定义方式

    自定义类型处理器需要实现`org.apache.ibatis.type.TypeHandler`接口,并重写`setNonNullParameter`、`getNullableResult`和`getResultFromCursor`方法。 ```java public class CustomTypeHandler implements ...

    ibatis自定义数据类型在不支持中文的数据库存储汉字

    TypeHandler是`iBatis`处理Java类型和JDBC类型之间转换的接口。通过创建一个自定义的TypeHandler,我们可以实现将中文字符串转化为数据库能识别的格式,如Base64编码,存储到数据库中;在读取时,再将数据解码回中文...

    简单小例子登录,spirng+struts+Ibatis+xml、json解析

    spirng+struts+Ibatis+xml、json解析

    ibatis 支持枚举类型

    Ibatis对枚举类型的原生支持可能不如实体类那样直观,但通过一些策略,我们可以实现枚举与数据库字段之间的映射。以下将详细解释如何在Ibatis中处理枚举类型。 首先,我们需要定义枚举类。枚举类通常包含若干枚举...

    iBATIS操作Oracle CLOB数据

    &lt;typeHandler handler="org.apache.ibatis.type.OracleClobHandler" /&gt; ``` 6. **性能优化**:处理CLOB数据时,注意避免一次性加载整个CLOB内容到内存中,可以分块读取或延迟加载。 7. **事务管理**:由于CLOB...

    mybatis自定义类型处理器TypehHandler示例详解

    默认情况下,MyBatis提供了内置的类型处理器(TypeHandler)来自动完成Java类型与JDBC类型之间的转换。然而,当我们遇到一些特定的需求,如数据加密、状态转换等,就需要自定义类型处理器来满足这些需求。本文将深入...

    ibatis.util包

    7. **TypeHandlerRegistry**: 这是Ibatis的核心组件之一,负责管理所有的类型处理器(TypeHandler)。TypeHandler是Ibatis中处理Java类型和数据库类型之间转换的关键,`TypeHandlerRegistry`可以根据Java类型或JDBC...

    ibatis实现原理解析

    在本篇文章中,我们将深入解析Ibatis的实现原理,探讨其核心功能、工作流程以及优势。 一、Ibatis的核心概念 1. SQL映射文件:Ibatis通过XML或注解方式定义SQL语句,这些语句被封装在SQL映射文件中。映射文件包含...

    ibatis-sqlmap-2.3.4.741-sources.zip_4 3 2 1_ibatis-sqlm_ibatis-s

    iBATIS SQLMap的这个版本增加了对多种数据库的透明支持,这意味着开发者无需关心底层使用的具体数据库类型,只需使用通用的API,框架会自动根据配置转换为对应数据库的SQL,降低了跨数据库迁移的成本。 从压缩包子...

    ibatis相关的common,dao,sqlmap包

    Ibatis-common 包含了Ibatis框架的基础工具类和通用模块,提供了诸如类型处理器(TypeHandler)、结果映射(ResultMap)等核心功能。TypeHandler是Ibatis中用于处理Java类型与数据库类型的转换,确保数据在Java对象...

    ibatis类型

    标题 "ibatis类型" 暗示我们讨论的是关于iBATIS这个持久层框架的一些特定类型或组件。iBATIS是Java开发中的一个流行数据库访问框架,它允许开发者将SQL语句直接集成到XML配置文件中,实现了SQL与Java代码的分离,...

    ibatis-common.jar包

    2. **TypeHandler**:TypeHandler是Ibatis处理Java类型和数据库类型之间转换的关键接口。每个数据库字段类型都可能对应一个TypeHandler,用于将Java对象转化为SQL语句中的参数,或者将查询结果转化为Java对象。例如...

    ibatis的3个jar包.rar

    2. **ibatis-common-2.jar**:这个包提供了Ibatis框架的一系列通用工具和类,包括类型处理器(TypeHandler)用于处理Java类型与数据库类型的转换,以及ResultHandler结果集处理器,用于处理查询结果。此外,还包括了...

    ibatis demo,ibatis例子,ibatis示例

    Ibatis提供了多种方式来实现映射,如自动类型匹配、自定义类型处理器、复杂关联映射等。 7. **缓存机制**:Ibatis内置了本地缓存和二级缓存,可以提高数据读取速度。本地缓存作用于单个SqlSession,而二级缓存则...

    根据MyBatis或iBatis的SQLMapper文件反向生成数据库表

    根据MyBatis或iBatis的SQLMapper文件解析生成数据库表,通常是指通过解析MyBatis或iBatis的SQLMapper文件中的SQL语句,然后根据这些SQL语句来生成对应的数据库表结构。这样的需求可能源于需要将已有的SQLMapper文件...

    ibatis开发包(common+sqlmap+dao)

    例如,`org.apache.ibatis.type.TypeHandler`接口定义了如何在Java对象和数据库字段之间进行转换的逻辑,这对于处理复杂的数据类型尤其有用。 2. **ibatis-sqlmap-2.jar**: 这是Ibatis的核心组件,实现了SQL映射...

    iBATIS 框架简介

    6. **TypeHandler**和**DataExchange**:在参数映射过程中,TypeHandler负责Java类型到数据库类型的转换,DataExchange则完成参数值的复制。 7. **SqlMapSession的创建与释放**:SqlMapSession负责数据库连接的创建...

    iBatis框架源码剖析

    iBATIS一词来源于“internet”和“abatis”的组合,是一个由Clinton Begin在2001年发起的开放源代码项目。于2010年6月16号被谷歌托管,改名为MyBatis。是一个基于SQL映射支持Java和·NET的持久层框架。

Global site tag (gtag.js) - Google Analytics