`

ibatis源码学习

 
阅读更多

ibatis版本号:

2.3.0

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

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

 

各大包结构和作用:

 

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:

 


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

对外接口调用如下:

Java代码  收藏代码
  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:

 

 

 

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

 元数据接口

 

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

Java代码  收藏代码
  1. /** 
  2. * Interface for getting data into, and out of a mapped statement 
  3. */  
  4. public interface 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);  
  18. }  

 

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代码  收藏代码
  1. public interface 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.   
  10. }  

 

 StringTypeHandler——String类型帮助类

Java代码  收藏代码
  1. public class StringTypeHandler extends BaseTypeHandler implements 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.   }  
  25. }  

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

 

Java代码  收藏代码
  1. /** 
  2.  * Not much of a suprise, this is a factory class for TypeHandler objects. 
  3.  */  
  4. public class 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.classnew StringTypeHandler());  
  24.     register(String.class"CLOB"new CustomTypeHandler(new ClobTypeHandlerCallback()));  
  25.     register(String.class"LONGVARCHAR"new CustomTypeHandler(new ClobTypeHandlerCallback()));  
  26.   
  27.     register(byte[].classnew 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.   
  124. }  

 

 

 Mapping包

 

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

 

    UML:

 

 

ParameterMap接口

 

Java代码  收藏代码
  1. public interface 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.   
  18. }  

 

ParameterMapping接口

 

Java代码  收藏代码
  1. public interface ParameterMapping {  
  2.   
  3.   public String getPropertyName();  
  4.   
  5.   public boolean isOutputAllowed();  
  6.   
  7. }  

 

BasicParameterMapping实现类:

 

Java代码  收藏代码
  1. public class BasicParameterMapping implements ParameterMapping {  
  2.   
  3.   private static final String MODE_INOUT = "INOUT";  
  4.   private static final String MODE_OUT = "OUT";  
  5.   private static final 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.   }  
  39. }  

 

 

 

BasicParameterMap实现类

 

Java代码  收藏代码
  1. public class BasicParameterMap implements 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 (typeHandler instanceof 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.   
  91. }  

 

分享到:
评论

相关推荐

    最新ibatis 源码

    ibatis源码 学习参考 对于学习ibatis很有帮助

    ibatis源码,ibatis源码 ibatis源码 ibatis源码

    《深入解析iBatis源码》 iBatis,一个优秀的Java持久层框架,以其轻量级、灵活的特性在众多ORM(Object-Relational Mapping)框架中独树一帜。iBatis的核心在于它的SQL映射机制,它将数据库操作与业务逻辑解耦,...

    ibatis源码

    描述中的"ibatis框架源码剖析书中附带的光盘,ibatis源码分析"暗示这可能是一个学习资源,用于深入理解iBATIS的工作原理,可能包括了对源码的详细解读和分析。 **iBATIS核心知识点** 1. **SQL映射**:iBATIS的核心...

    ibatis源码+api文档+jar包

    3. 学习设计模式:Ibatis的源码中应用了许多经典的设计模式,如工厂模式、单例模式、代理模式等,这对于提升编程技能非常有帮助。 最后,API文档是开发者的重要参考材料,它详细解释了每个类、接口和方法的功能、...

    iBATIS框架源码剖析源码

    通过深入分析iBATIS的源码,开发者不仅可以了解其工作原理,还能学习到设计模式、数据库访问的最佳实践以及如何优雅地处理数据库操作。对于提升Java开发者的技能和理解数据库访问层的实现有极大的帮助。在实际开发中...

    ibatis框架源码剖析光盘资料

    总的来说,ibatis框架源码的学习不仅可以帮助我们理解其工作原理,提升开发效率,还能为我们提供一种思考问题的角度,理解数据访问层的设计模式。通过对源码的深入剖析,我们可以更好地解决实际项目中的问题,进行...

    ibatis 学习源码

    PUBLIC "-//iBATIS.com//DTD SQL Map Config 2.0//EN" "http://www.ibatis.com/dtd/sql-map-config-2.dtd"&gt; cacheModelsEnabled="true" enhancementEnabled="true" lazyLoadingEnabled="true" ...

    springMVC+ibatis的源码

    通过学习和分析这个源码,开发者不仅可以深入了解SpringMVC和iBatis的协同工作原理,还可以掌握如何在Eclipse这样的IDE中配置和运行这样的项目。这有助于提升对MVC模式的理解,提高数据库操作的能力,以及熟练运用...

    iBatis源码jar包以后上传

    这个“iBatis源码jar包以后上传”可能指的是将要分享或者提供iBatis的源码jar包,以便于开发者深入学习和理解其内部工作原理。 首先,让我们来了解一下iBatis的基本概念和工作流程。iBatis的核心是SQL Map配置文件...

    iBATIS2.3.4 jar包及源码

    对于开发者来说,源码能够帮助他们深入了解iBATIS的工作原理,便于学习、调试和扩展。如果在使用过程中遇到问题,查看源码可以快速定位并解决问题。通常,将源码放在`lib`目录下并不常见,因为源码主要用于开发和...

    ibatis学习资料汇总

    深入研究iBatis源码有助于理解其内部工作原理,包括如何解析XML配置文件,如何执行SQL语句,以及如何进行结果映射。源码分析可以帮助开发者更好地定制和优化自己的应用。 六、iBatis实践项目 通过实践项目,可以...

    ibatis2.3源码

    通过深入研究iBATIS 2.3的源码,开发者不仅可以了解其实现细节,还可以学习到如何设计一个高效的持久层框架,提升自己的编程技巧和设计能力。同时,这也为那些希望在现有基础上定制或优化iBATIS功能的开发者提供了...

    IBatis源码+xsd+帮助

    一、**IBatis源码分析** IBatis的源码是开源的,这对于开发者来说是一份宝贵的资源,可以让我们深入了解其工作原理和内部机制。通过阅读源码,我们可以学习到以下知识点: 1. **动态SQL**:IBatis的核心功能之一...

    ibatisDemo 入门源码

    《IbatisDemo入门源码详解》 IbatisDemo是一个典型的基于Ibatis框架的入门示例,它为我们展示了如何在Java项目中使用Ibatis进行数据库操作。Ibatis,一个优秀的持久层框架,它允许开发者将SQL语句直接写在配置文件...

    iBATIS框架源码剖析pdf第二部分

    在"iBATIS框架源码剖析pdf第二部分"中,我们将深入探讨iBATIS的核心组件、工作原理以及其实现细节。 首先,我们来了解一下iBATIS的基本架构。iBATIS由四大核心部分组成:SqlMapConfig.xml配置文件、SqlMap接口、SQL...

    iBATIS开放源代码

    尽管现代有许多更先进的ORM框架如MyBatis(iBATIS的后继者),但iBATIS的历史地位和其开创性的设计理念仍然值得我们学习和借鉴。通过深入理解iBATIS,开发者可以更好地掌握数据库操作的技巧,提升项目开发效率。

    ibatis学习

    标题 "ibatis学习" 暗示我们即将探讨的是关于Ibatis,一个著名的Java持久层框架,它允许开发者将SQL语句直接写在配置文件中,以实现灵活的数据访问。Ibatis提供了简单易用的API,使得数据库操作与业务逻辑解耦,提高...

    apache开源项目源码ibatis-3-core-src-3.0.0.227(ibatis框架java源程序)

    apache开源项目源码ibatis-3-core-src-3.0.0.227 ibatis框架java源程序 spring,struts,hibernate,ibatis,框架源码 ...apache开源组织开发的开源项目源码,其优良的代码风格和高质量的源码是学习者难得的学习资料!

Global site tag (gtag.js) - Google Analytics