ibatis源码学习4_源码包结构

时间:2022-06-04 21:42:43

ibatis版本号:

2.3.0

Build Date: 2006/11/30 17:16
Build Number: 677

ibatis的技术是从xml里面字符串转换成JAVA对象,对象填充JDBC的statement查询,然后从resultset取对象返回,另外利用ThreadLocal实现线程安全,JDBC保证了事务控制,cache(三方库)实现缓存的dao框架。

各大包结构和作用:
ibatis源码学习4_源码包结构

1,accessplan—

2,builder.xml

3,cache

4,datasource

5,exchange—ResultMap(sql结果类型结构)和ParameterMap(sql条件类型结果)与值的相互转换

6,execution

7,impl

8,mapping

9,scop

10,transaction

11,type—jdbc的Statement和ResultSet 与 java.lang.Object对象的相互转换。

Accessplan

uml:


ibatis源码学习4_源码包结构

Accessplan对外只提供个Factory,这种“封闭”设计可以借鉴:

对外接口调用如下:

Java代码  ibatis源码学习4_源码包结构
  1. parameterPlan = AccessPlanFactory.getAccessPlan(parameterMap.getParameterClass(), parameterPropNames); 

其中parameterMap.getParameterClass(),是映射的CLASS,就是XML里parameterXXX里的类,后面那个是类的成员变量,ParameterMapping是映射元素类,如下:

  // 从某个映射对象中取出所有元素

  ParameterMapping[] parameterMappings = parameterMap.getParameterMappings();


        String[] parameterPropNames = new String[parameterMappings.length];
        for (int i = 0; i < parameterPropNames.length; i++) {

// 从元素中取出被映射对象的成员名
          parameterPropNames[i] = parameterMappings[i].getPropertyName();
        }


UML:


ibatis源码学习4_源码包结构

ibatis源码学习4_源码包结构

ResultGetter和ParameterSetter的设计看来是为了TypeHandlerCallback扩展的复杂数据类型所用。为什么需要在这中间加一层呢? 可能是因为数据的复杂性吧,把特例和一般分离出来,代码看上去似乎优雅些。继续深入。

元数据接口

TypeHandler接口的抽象意义——Interface for getting data into, and out of a mapped statement,主要的作用是把Object那些对象set到jdbc的statement,以及从resultset结果集中获取那些Object对象。

Java代码  ibatis源码学习4_源码包结构
  1. /**
  2. * Interface for getting data into, and out of a mapped statement
  3. */ 
  4. publicinterface TypeHandler { 
  5.   // para向第i个位置填充ps. 
  6.    public void setParameter(PreparedStatement ps,int i, Object parameter, String jdbcType) 
  7.       throws SQLException; 
  8.   // 根据rs结果集某字段名取值 
  9.   public Object getResult(ResultSet rs, String columnName) 
  10.       throws SQLException; 
  11.   public Object getResult(ResultSet rs, int columnIndex) 
  12.       throws SQLException; 
  13.   /**
  14.    * Converts the String to the type that this handler deals with
  15.    */ 
  16.   public Object valueOf(String s); 
  17.   public boolean equals(Object object, String string); 

TypeHandlerCallback接口抽象意义为:

A simple interface for implementing custom type handlers.
Using this interface, you can implement a type handler that
will perform customized processing before parameters are set
on a PreparedStatement and after values are retrieved from
a ResultSet.

Java代码  ibatis源码学习4_源码包结构
  1. publicinterface TypeHandlerCallback { 
  2.  
  3.   public void setParameter(ParameterSetter setter, Object parameter)// 同上 
  4.       throws SQLException; 
  5.  
  6.   public Object getResult(ResultGetter getter) // 同上 
  7.       throws SQLException; 
  8.   public Object valueOf(String s); 
  9.  

StringTypeHandler——String类型帮助类

Java代码  ibatis源码学习4_源码包结构
  1. publicclass StringTypeHandlerextends BaseTypeHandlerimplements TypeHandler { 
  2.  
  3.   public void setParameter(PreparedStatement ps,int i, Object parameter, String jdbcType) 
  4.       throws SQLException { 
  5.     ps.setString(i, ((String) parameter)); 
  6.   } 
  7.   public Object getResult(ResultSet rs, String columnName) 
  8.       throws SQLException { 
  9.     Object s = rs.getString(columnName); // 很熟悉的jdbc编程吧 
  10.     if (rs.wasNull()) { 
  11.       return null
  12.     } else
  13.       return s; 
  14.     } 
  15.   } 
  16.   public Object getResult(ResultSet rs, int columnIndex) 
  17.       throws SQLException { 
  18.     Object s = rs.getString(columnIndex); 
  19.     if (rs.wasNull()) { 
  20.       return null
  21.     } else
  22.       return s; 
  23.     } 
  24.   } 

最后“元数据”这块剩下最后一个Factory管理类:TypeHandlerFactory

Java代码  ibatis源码学习4_源码包结构
  1. /**
  2. * Not much of a suprise, this is a factory class for TypeHandler objects.
  3. */ 
  4. publicclass TypeHandlerFactory { 
  5.  
  6.   private final Map typeHandlerMap =new HashMap();// 用final Map来存储类型转换的帮助类 
  7.   private final TypeHandler unknownTypeHandler =new UnknownTypeHandler(this); 
  8.   private final HashMap typeAliases =new HashMap();// 保存type助记符,为什么呢? 
  9.   /**
  10.    * Default constructor
  11.    */ 
  12.   public TypeHandlerFactory() { 
  13.     TypeHandler handler; 
  14.  
  15.     handler = new BooleanTypeHandler(); 
  16.     register(Boolean.class, handler);// 实际上把handler放入布尔值的map,然后再放入typeMap里。 
  17.   register(boolean.class, handler); 
  18.  
  19.     handler = new ByteTypeHandler(); 
  20.     register(Byte.class, handler); 
  21.     register(byte.class, handler); 
  22.  
  23.     register(String.class,new StringTypeHandler()); 
  24.     register(String.class,"CLOB",new CustomTypeHandler(new ClobTypeHandlerCallback())); 
  25.     register(String.class,"LONGVARCHAR",new CustomTypeHandler(new ClobTypeHandlerCallback())); 
  26.  
  27.     register(byte[].class,new ByteArrayTypeHandler()); 
  28.     register(byte[].class,"BLOB",new CustomTypeHandler(new BlobTypeHandlerCallback())); 
  29.     register(byte[].class,"LONGVARBINARY",new CustomTypeHandler(new BlobTypeHandlerCallback())); 
  30.    .... 
  31.     putTypeAlias("string", String.class.getName()); 
  32.     putTypeAlias("byte", Byte.class.getName()); 
  33.     putTypeAlias("long", Long.class.getName()); 
  34.    .... 
  35.   } 
  36.  
  37.   /* Public Methods */ 
  38.  
  39.   public TypeHandler getTypeHandler(Class type, String jdbcType) { 
  40.     Map jdbcHandlerMap = (Map) typeHandlerMap.get(type); 
  41.     TypeHandler handler = null
  42.     if (jdbcHandlerMap != null) { 
  43.       handler = (TypeHandler) jdbcHandlerMap.get(jdbcType); 
  44.       if (handler == null) { 
  45.         handler = (TypeHandler) jdbcHandlerMap.get(null); 
  46.       } 
  47.     } 
  48.     return handler; 
  49.   } 
  50.  
  51.   /**
  52.    * When in doubt, get the "unknown" type handler
  53.    *
  54.    * @return - if I told you, it would not be unknown, would it?
  55.    */ 
  56.   public TypeHandler getUnkownTypeHandler() { 
  57.     return unknownTypeHandler; 
  58.   } 
  59.  
  60.  
  61.   /**
  62.    * Tells you if a particular class has a TypeHandler
  63.    *
  64.    * @param type - the class
  65.    *
  66.    * @return - true if there is a TypeHandler
  67.    */ 
  68.   public boolean hasTypeHandler(Class type) { 
  69.     return getTypeHandler(type) != null
  70.   } 
  71.  
  72.   /**
  73.    * Register (add) a type handler for a class and JDBC type
  74.    *
  75.    * @param type - the class
  76.    * @param jdbcType - the JDBC type
  77.    * @param handler - the handler instance
  78.    */ 
  79.   public void register(Class type, String jdbcType, TypeHandler handler) { 
  80.     Map map = (Map) typeHandlerMap.get(type); 
  81.     if (map == null) { 
  82.       map = new HashMap(); 
  83.       typeHandlerMap.put(type, map); 
  84.     } 
  85.     map.put(jdbcType, handler); 
  86.   } 
  87.  
  88.   /**
  89.    * Lookup an aliased class and return it's REAL name
  90.    *
  91.    * @param string - the alias
  92.    *
  93.    * @return - the REAL name
  94.    */ 
  95.   public String resolveAlias(String string) { 
  96.     String key = null
  97.     if(string != null
  98.       key = string.toLowerCase(); 
  99.     String value = null
  100.     if (typeAliases.containsKey(key)) { 
  101.       value = (String) typeAliases.get(key); 
  102.     } else
  103.       value = string; 
  104.     } 
  105.  
  106.     return value; 
  107.   } 
  108.  
  109.   /**
  110.    * Adds a type alias that is case insensitive.  All of the following String, string, StRiNg will equate to the same alias.
  111.    * @param alias - the alias
  112.    * @param value - the real class name
  113.    */ 
  114.   public void putTypeAlias(String alias, String value) { 
  115.     String key = null
  116.     if(alias != null
  117.       key = alias.toLowerCase(); 
  118.     if (typeAliases.containsKey(key) && !typeAliases.get(key).equals(value)) { 
  119.       throw new SqlMapException("Error in XmlSqlMapClientBuilder.  Alias name conflict occurred.  The alias '" + key +"' is already mapped to the value '" + typeAliases.get(alias) +"'."); 
  120.     } 
  121.     typeAliases.put(key, value); 
  122.   } 
  123.  

Mapping包

   --parameter包意义——主要负责数据类型转换,把xml写的字符串映射成正确的类型,以上type包是解决了object到type的转换。

    UML:

ibatis源码学习4_源码包结构

ParameterMap接口

Java代码  ibatis源码学习4_源码包结构
  1. publicinterface ParameterMap { 
  2.  
  3.   public String getId(); 
  4.  
  5.   public void setParameters(RequestScope request, PreparedStatement ps, Object[] parameters) 
  6.       throws SQLException; 
  7.  
  8.   public Object[] getParameterObjectValues(RequestScope request, Object parameterObject); 
  9.  
  10.   public CacheKey getCacheKey(RequestScope request, Object parameterObject); 
  11.  
  12.   public void refreshParameterObjectValues(RequestScope request, Object parameterObject, Object[] values); 
  13.  
  14.   public ParameterMapping[] getParameterMappings(); 
  15.  
  16.   public Class getParameterClass(); 
  17.  

ParameterMapping接口

Java代码  ibatis源码学习4_源码包结构
  1. publicinterface ParameterMapping { 
  2.  
  3.   public String getPropertyName(); 
  4.  
  5.   public boolean isOutputAllowed(); 
  6.  

BasicParameterMapping实现类:

Java代码  ibatis源码学习4_源码包结构
  1. publicclass BasicParameterMappingimplements ParameterMapping { 
  2.  
  3.   private staticfinal String MODE_INOUT ="INOUT"
  4.   private staticfinal String MODE_OUT ="OUT"
  5.   private staticfinal String MODE_IN ="IN"
  6.  
  7.   private String propertyName; // 从XML文件里读取需要转换的类型名 
  8.   private TypeHandler typeHandler; // 对象转换相应类型的工具map 
  9.   private String typeName; // this is used for REF types or user-defined types 
  10.   private int jdbcType; 
  11.   private String jdbcTypeName; 
  12.   private String nullValue; 
  13.   private String mode; 
  14.   private boolean inputAllowed; 
  15.   private boolean outputAllowed; 
  16.   private Class javaType; // 需要转换的类型class 
  17.   private String resultMapName; // 结果map名称 
  18.   private Integer numericScale; 
  19.  
  20.   private String errorString; 
  21.  
  22.   public BasicParameterMapping() { 
  23.     mode = "IN"
  24.     inputAllowed = true
  25.     outputAllowed = false
  26.   } 
  27.  
  28.   public void setJavaTypeName(String javaTypeName) { 
  29.     try
  30.       if (javaTypeName == null) { 
  31.         this.javaType = null
  32.       } else {// 通过getClassLoader().loadClass(className);来获得实例 
  33.         this.javaType = Resources.classForName(javaTypeName); 
  34.       } 
  35.     } catch (ClassNotFoundException e) { 
  36.       throw new SqlMapException("Error setting javaType property of ParameterMap.  Cause: " + e, e); 
  37.     } 
  38.   } 

BasicParameterMap实现类

Java代码  ibatis源码学习4_源码包结构
  1. publicclass BasicParameterMapimplements ParameterMap { 
  2.  
  3.   private String id; 
  4.   private Class parameterClass; 
  5.  
  6.   private ParameterMapping[] parameterMappings; 
  7.   private DataExchange dataExchange; 
  8.  
  9.   private String resource; 
  10.  
  11.   private Map parameterMappingIndex = new HashMap(); 
  12.   private SqlMapExecutorDelegate delegate; 
  13.  
  14.  
  15.   public void setParameterMappingList(List parameterMappingList) { 
  16.     this.parameterMappings = (BasicParameterMapping[]) parameterMappingList.toArray(new BasicParameterMapping[parameterMappingList.size()]); 
  17.     for (int i =0; i < parameterMappings.length; i++) { 
  18.       parameterMappingIndex.put(parameterMappings[i].getPropertyName(),new Integer(i)); 
  19.     } 
  20.     Map props = new HashMap(); 
  21.     props.put("map",this); 
  22.  
  23.     dataExchange = delegate.getDataExchangeFactory().getDataExchangeForClass(parameterClass); 
  24.     dataExchange.initialize(props); 
  25.   } 
  26.  
  27.   /**
  28.    * @param ps
  29.    * @param parameters
  30.    * @throws java.sql.SQLException
  31.    */ 
  32.   public void setParameters(RequestScope request, PreparedStatement ps, Object[] parameters) 
  33.       throws SQLException { 
  34.  
  35.     ErrorContext errorContext = request.getErrorContext(); 
  36.     errorContext.setActivity("applying a parameter map"); 
  37.     errorContext.setObjectId(this.getId()); 
  38.     errorContext.setResource(this.getResource()); 
  39.     errorContext.setMoreInfo("Check the parameter map."); 
  40.  
  41.     if (parameterMappings != null) { 
  42.       for (int i =0; i < parameterMappings.length; i++) { 
  43.         BasicParameterMapping mapping = (BasicParameterMapping) parameterMappings[i]; 
  44.         errorContext.setMoreInfo(mapping.getErrorString()); 
  45.         if (mapping.isInputAllowed()) { 
  46.           setParameter(ps, mapping, parameters, i); 
  47.         } 
  48.       } 
  49.     } 
  50.   } 
  51.  
  52.   public Object[] getParameterObjectValues(RequestScope request, Object parameterObject) { 
  53.     return dataExchange.getData(request, this, parameterObject); 
  54.   } 
  55.  
  56.   public CacheKey getCacheKey(RequestScope request, Object parameterObject) { 
  57.     return dataExchange.getCacheKey(request, this, parameterObject); 
  58.   } 
  59.  
  60.   public void refreshParameterObjectValues(RequestScope request, Object parameterObject, Object[] values) { 
  61.     dataExchange.setData(request, this, parameterObject, values); 
  62.   } 
  63.  
  64.   protected void setParameter(PreparedStatement ps, BasicParameterMapping mapping, Object[] parameters,int i)throws SQLException { 
  65.     Object value = parameters[i]; 
  66.     // Apply Null Value 
  67.     String nullValueString = mapping.getNullValue(); 
  68.     if (nullValueString != null) { 
  69.       TypeHandler handler = mapping.getTypeHandler(); 
  70.       if (handler.equals(value, nullValueString)) { 
  71.         value = null
  72.       } 
  73.     } 
  74.  
  75.     // Set Parameter 
  76.     TypeHandler typeHandler = mapping.getTypeHandler(); 
  77.     if (value != null) { 
  78.       typeHandler.setParameter(ps, i + 1, value, mapping.getJdbcTypeName()); 
  79.     } else if (typeHandlerinstanceof CustomTypeHandler) { 
  80.       typeHandler.setParameter(ps, i + 1, value, mapping.getJdbcTypeName()); 
  81.     } else
  82.       int jdbcType = mapping.getJdbcType(); 
  83.       if (jdbcType != JdbcTypeRegistry.UNKNOWN_TYPE) { 
  84.         ps.setNull(i + 1, jdbcType); 
  85.       } else
  86.         ps.setNull(i + 1, Types.OTHER); 
  87.       } 
  88.     } 
  89.   } 
  90.