Ibatis的类型处理器TypeHandler解析

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

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

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

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

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

  1. <typeHandlers>
  2. <typeHandlerjdbcType="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. StringpropertyName=childAttributes.getProperty("property");
  2. StringnullValue=childAttributes.getProperty("nullValue");
  3. StringjdbcType=childAttributes.getProperty("jdbcType");
  4. StringjavaType=childAttributes.getProperty("javaType");
  5. StringcolumnName=childAttributes.getProperty("column");
  6. StringcolumnIndex=childAttributes.getProperty("columnIndex");
  7. StringstatementName=childAttributes.getProperty("select");
  8. StringresultMapName=childAttributes.getProperty("resultMap");
  9. Stringcallback=childAttributes.getProperty("typeHandler");
  10. callback=vars.typeHandlerFactory.resolveAlias(callback);
  11. javaType=vars.typeHandlerFactory.resolveAlias(javaType);
  12. TypeHandlerhandler=null;
  13. if(callback!=null){ // 注意这里,如果配置了就使用这个配置的handler
  14. Objectimpl=Resources.classForName(callback).newInstance();
  15. if(implinstanceofTypeHandlerCallback){
  16. handler=newCustomTypeHandler((TypeHandlerCallback)impl);
  17. }elseif(implinstanceofTypeHandler){
  18. handler=(TypeHandler)impl;
  19. }else{
  20. thrownewNestedRuntimeException("Theclass''isnotavalidimplementationofTypeHandlerorTypeHandlerCallback");
  21. }
  22. }else{//如果没有配置,就到这里来找
  23. handler=resolveTypeHandler(vars.client.getDelegate().getTypeHandlerFactory(),vars.currentResultMap.getResultClass(),propertyName,javaType,jdbcType,true);
  24. }

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

  1. publicTypeHandlerresolveTypeHandler(TypeHandlerFactorytypeHandlerFactory,Classclazz,StringpropertyName,StringjavaType,StringjdbcType,booleanuseSetterToResolve){
  2. TypeHandlerhandler=null;
  3. if(clazz==null){
  4. //Unknown
  5. handler=typeHandlerFactory.getUnkownTypeHandler();
  6. }elseif(DomTypeMarker.class.isAssignableFrom(clazz)){
  7. //DOM
  8. handler=typeHandlerFactory.getTypeHandler(String.class,jdbcType);
  9. }elseif(java.util.Map.class.isAssignableFrom(clazz)){
  10. //Map
  11. if(javaType==null){
  12. handler=typeHandlerFactory.getUnkownTypeHandler();//BUG1012591-typeHandlerFactory.getTypeHandler(java.lang.Object.class,jdbcType);
  13. }else{
  14. try{
  15. ClassjavaClass=Resources.classForName(javaType);
  16. handler=typeHandlerFactory.getTypeHandler(javaClass,jdbcType);
  17. }catch(Exceptione){
  18. thrownewNestedRuntimeException("Error.CouldnotsetTypeHandler.Cause:"+e,e);
  19. }
  20. }
  21. }elseif(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. Classtype=PROBE.getPropertyTypeForSetter(clazz,propertyName);
  29. handler=typeHandlerFactory.getTypeHandler(type,jdbcType);
  30. }else{
  31. Classtype=PROBE.getPropertyTypeForGetter(clazz,propertyName);
  32. handler=typeHandlerFactory.getTypeHandler(type,jdbcType);
  33. }
  34. }else{
  35. try{
  36. ClassjavaClass=Resources.classForName(javaType);
  37. handler=typeHandlerFactory.getTypeHandler(javaClass,jdbcType);
  38. }catch(Exceptione){
  39. thrownewNestedRuntimeException("Error.CouldnotsetTypeHandler.Cause:"+e,e);
  40. }
  41. }
  42. }
  43. returnhandler;
  44. }
  45. 相信大家已经很明白了,其实要找一个Handler,主要就是需要javaType和jdbcType,而这两个参数要么通过反射得到,要么通过配置文件中得到。因此,为了明确我们一般都在配置文件中进行申明。
  46. 最后来看一点 typeHandlerFactory.getTypeHandler(clazz,jdbcType)是怎么实现的。
    1. publicTypeHandlergetTypeHandler(Classtype,StringjdbcType){
    2. MapjdbcHandlerMap=(Map)typeHandlerMap.get(type);//首先根据JAVA类型
    3. TypeHandlerhandler=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. returnhandler;
    11. }
  47. 其实一个Handler=javaType+jdbcType 。

你可能感兴趣的:(TypeHandler)