`
C_J
  • 浏览: 127872 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

ibatis源码分析(待续...) in 2009

阅读更多

 

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,这种“封闭”设计可以借鉴:

对外接口调用如下:

    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对象。

/**
* Interface for getting data into, and out of a mapped statement
*/
public interface TypeHandler {
  // para向第i个位置填充ps.
   public void setParameter(PreparedStatement ps, int i, Object parameter, String jdbcType)
      throws SQLException;
  // 根据rs结果集某字段名取值
  public Object getResult(ResultSet rs, String columnName)
      throws SQLException;
  public Object getResult(ResultSet rs, int columnIndex)
      throws SQLException;
  /**
   * Converts the String to the type that this handler deals with
   */
  public Object valueOf(String s);
  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.

 

public interface TypeHandlerCallback {

  public void setParameter(ParameterSetter setter, Object parameter) // 同上
      throws SQLException;

  public Object getResult(ResultGetter getter) // 同上
      throws SQLException;
  public Object valueOf(String s);

}

 

 StringTypeHandler——String类型帮助类

public class StringTypeHandler extends BaseTypeHandler implements TypeHandler {

  public void setParameter(PreparedStatement ps, int i, Object parameter, String jdbcType)
      throws SQLException {
    ps.setString(i, ((String) parameter));
  }
  public Object getResult(ResultSet rs, String columnName)
      throws SQLException {
    Object s = rs.getString(columnName); // 很熟悉的jdbc编程吧
    if (rs.wasNull()) {
      return null;
    } else {
      return s;
    }
  }
  public Object getResult(ResultSet rs, int columnIndex)
      throws SQLException {
    Object s = rs.getString(columnIndex);
    if (rs.wasNull()) {
      return null;
    } else {
      return s;
    }
  }
}

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

 

/**
 * Not much of a suprise, this is a factory class for TypeHandler objects.
 */
public class TypeHandlerFactory {

  private final Map typeHandlerMap = new HashMap(); // 用final Map来存储类型转换的帮助类
  private final TypeHandler unknownTypeHandler = new UnknownTypeHandler(this);
  private final HashMap typeAliases = new HashMap();// 保存type助记符,为什么呢?
  /**
   * Default constructor
   */
  public TypeHandlerFactory() {
    TypeHandler handler;

    handler = new BooleanTypeHandler();
    register(Boolean.class, handler);// 实际上把handler放入布尔值的map,然后再放入typeMap里。
  register(boolean.class, handler);

    handler = new ByteTypeHandler();
    register(Byte.class, handler);
    register(byte.class, handler);

    register(String.class, new StringTypeHandler());
    register(String.class, "CLOB", new CustomTypeHandler(new ClobTypeHandlerCallback()));
    register(String.class, "LONGVARCHAR", new CustomTypeHandler(new ClobTypeHandlerCallback()));

    register(byte[].class, new ByteArrayTypeHandler());
    register(byte[].class, "BLOB", new CustomTypeHandler(new BlobTypeHandlerCallback()));
    register(byte[].class, "LONGVARBINARY", new CustomTypeHandler(new BlobTypeHandlerCallback()));
   ....
    putTypeAlias("string", String.class.getName());
    putTypeAlias("byte", Byte.class.getName());
    putTypeAlias("long", Long.class.getName());
   ....
  }

  /* Public Methods */

  public TypeHandler getTypeHandler(Class type, String jdbcType) {
    Map jdbcHandlerMap = (Map) typeHandlerMap.get(type);
    TypeHandler handler = null;
    if (jdbcHandlerMap != null) {
      handler = (TypeHandler) jdbcHandlerMap.get(jdbcType);
      if (handler == null) {
        handler = (TypeHandler) jdbcHandlerMap.get(null);
      }
    }
    return handler;
  }

  /**
   * When in doubt, get the "unknown" type handler
   * 
   * @return - if I told you, it would not be unknown, would it?
   */
  public TypeHandler getUnkownTypeHandler() {
    return unknownTypeHandler;
  }


  /**
   * Tells you if a particular class has a TypeHandler
   * 
   * @param type - the class
   * 
   * @return - true if there is a TypeHandler
   */
  public boolean hasTypeHandler(Class type) {
    return getTypeHandler(type) != null;
  }

  /**
   * Register (add) a type handler for a class and JDBC type
   * 
   * @param type - the class
   * @param jdbcType - the JDBC type
   * @param handler - the handler instance
   */
  public void register(Class type, String jdbcType, TypeHandler handler) {
    Map map = (Map) typeHandlerMap.get(type);
    if (map == null) {
      map = new HashMap();
      typeHandlerMap.put(type, map);
    }
    map.put(jdbcType, handler);
  }

  /**
   * Lookup an aliased class and return it's REAL name
   * 
   * @param string - the alias
   * 
   * @return - the REAL name
   */
  public String resolveAlias(String string) {
    String key = null;
    if(string != null)
      key = string.toLowerCase();
    String value = null;
    if (typeAliases.containsKey(key)) {
      value = (String) typeAliases.get(key);
    } else {
      value = string;
    }

    return value;
  }

  /**
   * Adds a type alias that is case insensitive.  All of the following String, string, StRiNg will equate to the same alias.
   * @param alias - the alias
   * @param value - the real class name
   */
  public void putTypeAlias(String alias, String value) {
    String key = null;
    if(alias != null)
      key = alias.toLowerCase();
    if (typeAliases.containsKey(key) && !typeAliases.get(key).equals(value)) {
      throw new SqlMapException("Error in XmlSqlMapClientBuilder.  Alias name conflict occurred.  The alias '" + key + "' is already mapped to the value '" + typeAliases.get(alias) + "'.");
    }
    typeAliases.put(key, value);
  }

}

 

 

 Mapping包

 

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

 

    UML:

 

 

ParameterMap接口

 

public interface ParameterMap {

  public String getId();

  public void setParameters(RequestScope request, PreparedStatement ps, Object[] parameters)
      throws SQLException;

  public Object[] getParameterObjectValues(RequestScope request, Object parameterObject);

  public CacheKey getCacheKey(RequestScope request, Object parameterObject);

  public void refreshParameterObjectValues(RequestScope request, Object parameterObject, Object[] values);

  public ParameterMapping[] getParameterMappings();

  public Class getParameterClass();

}

 

ParameterMapping接口

 

public interface ParameterMapping {

  public String getPropertyName();

  public boolean isOutputAllowed();

}

 

BasicParameterMapping实现类:

 

public class BasicParameterMapping implements ParameterMapping {

  private static final String MODE_INOUT = "INOUT";
  private static final String MODE_OUT = "OUT";
  private static final String MODE_IN = "IN";

  private String propertyName; // 从XML文件里读取需要转换的类型名
  private TypeHandler typeHandler; // 对象转换相应类型的工具map
  private String typeName; // this is used for REF types or user-defined types
  private int jdbcType;
  private String jdbcTypeName;
  private String nullValue;
  private String mode;
  private boolean inputAllowed;
  private boolean outputAllowed;
  private Class javaType; // 需要转换的类型class
  private String resultMapName; // 结果map名称
  private Integer numericScale;

  private String errorString;

  public BasicParameterMapping() {
    mode = "IN";
    inputAllowed = true;
    outputAllowed = false;
  }

  public void setJavaTypeName(String javaTypeName) {
    try {
      if (javaTypeName == null) {
        this.javaType = null;
      } else {// 通过getClassLoader().loadClass(className);来获得实例
        this.javaType = Resources.classForName(javaTypeName);
      }
    } catch (ClassNotFoundException e) {
      throw new SqlMapException("Error setting javaType property of ParameterMap.  Cause: " + e, e);
    }
  }
}

 

 

 

BasicParameterMap实现类

 

public class BasicParameterMap implements ParameterMap {

  private String id;
  private Class parameterClass;

  private ParameterMapping[] parameterMappings;
  private DataExchange dataExchange;

  private String resource;

  private Map parameterMappingIndex = new HashMap();
  private SqlMapExecutorDelegate delegate;


  public void setParameterMappingList(List parameterMappingList) {
    this.parameterMappings = (BasicParameterMapping[]) parameterMappingList.toArray(new BasicParameterMapping[parameterMappingList.size()]);
    for (int i = 0; i < parameterMappings.length; i++) {
      parameterMappingIndex.put(parameterMappings[i].getPropertyName(), new Integer(i));
    }
    Map props = new HashMap();
    props.put("map", this);

    dataExchange = delegate.getDataExchangeFactory().getDataExchangeForClass(parameterClass);
    dataExchange.initialize(props);
  }

  /**
   * @param ps
   * @param parameters
   * @throws java.sql.SQLException
   */
  public void setParameters(RequestScope request, PreparedStatement ps, Object[] parameters)
      throws SQLException {

    ErrorContext errorContext = request.getErrorContext();
    errorContext.setActivity("applying a parameter map");
    errorContext.setObjectId(this.getId());
    errorContext.setResource(this.getResource());
    errorContext.setMoreInfo("Check the parameter map.");

    if (parameterMappings != null) {
      for (int i = 0; i < parameterMappings.length; i++) {
        BasicParameterMapping mapping = (BasicParameterMapping) parameterMappings[i];
        errorContext.setMoreInfo(mapping.getErrorString());
        if (mapping.isInputAllowed()) {
          setParameter(ps, mapping, parameters, i);
        }
      }
    }
  }

  public Object[] getParameterObjectValues(RequestScope request, Object parameterObject) {
    return dataExchange.getData(request, this, parameterObject);
  }

  public CacheKey getCacheKey(RequestScope request, Object parameterObject) {
    return dataExchange.getCacheKey(request, this, parameterObject);
  }

  public void refreshParameterObjectValues(RequestScope request, Object parameterObject, Object[] values) {
    dataExchange.setData(request, this, parameterObject, values);
  }

  protected void setParameter(PreparedStatement ps, BasicParameterMapping mapping, Object[] parameters, int i) throws SQLException {
    Object value = parameters[i];
    // Apply Null Value
    String nullValueString = mapping.getNullValue();
    if (nullValueString != null) {
      TypeHandler handler = mapping.getTypeHandler();
      if (handler.equals(value, nullValueString)) {
        value = null;
      }
    }

    // Set Parameter
    TypeHandler typeHandler = mapping.getTypeHandler();
    if (value != null) {
      typeHandler.setParameter(ps, i + 1, value, mapping.getJdbcTypeName());
    } else if (typeHandler instanceof CustomTypeHandler) {
      typeHandler.setParameter(ps, i + 1, value, mapping.getJdbcTypeName());
    } else {
      int jdbcType = mapping.getJdbcType();
      if (jdbcType != JdbcTypeRegistry.UNKNOWN_TYPE) {
        ps.setNull(i + 1, jdbcType);
      } else {
        ps.setNull(i + 1, Types.OTHER);
      }
    }
  }

}

 

  • 大小: 16 KB
  • 大小: 15.8 KB
  • 大小: 18.2 KB
  • 大小: 8.9 KB
  • 大小: 21.4 KB
分享到:
评论

相关推荐

    IBatis.DataAccess.1.9.2

    包含IBatis.net 开发所需的Castle.DynamicProxy.dll,IBatisNet.Common.dll,IBatisNet.DataAccess.dll,IBatisNet.Common.dll以及相关配置文件

    ibatis-2.3.3.720.jar

    ibatis-2.3.3.720.jar

    IBatisNet.Common.1.6.2、IBatis.DataAccess.1.9.2、IBatis.DataMapper.1.6.2

    标题和描述中提到的"IBatisNet.Common.1.6.2、IBatis.DataAccess.1.9.2、IBatis.DataMapper.1.6.2"是针对一个名为IBatisNet的框架的不同组件的版本号。IBatisNet是一个在.NET平台上实现的开源持久层框架,它源于Java...

    ibatis-2.3.4.726.jar,ibatis-2.3.0.677.jar,ibatis-2.3.3.720.jar下载

    这里提到的是iBATIS的三个不同版本的jar包:ibatis-2.3.4.726.jar、ibatis-2.3.0.677.jar以及ibatis-2.3.3.720.jar。 首先,让我们深入了解iBATIS的核心概念和功能: 1. **SQL Map配置**:iBATIS的核心是SQL Map...

    IBatis.net-IBatis.DataAccess.1.9.2/IBatis.DataMapper.1.6.2

    本篇将深入探讨IBatis.Net的核心组件——IBatis.DataAccess.1.9.2和IBatis.DataMapper.1.6.2,以及它们在数据访问中的关键作用。 **一、IBatis.DataAccess** IBatis.DataAccess是IBatis.net框架的一部分,主要负责...

    IBatis.DataMapper.1.6.2.bin.zip

    本篇文章将围绕"IBatis.DataMapper.1.6.2.bin.zip"和"IBatis.DataMapper.1.9"这两个开发包,深入探讨其核心概念、功能特性以及版本间的差异,帮助开发者更好地理解和应用这一框架。 1. **IBatis DataMapper简介** ...

    ibatis2.3.4.8.jar 和 ibatis-2.3.4.726.jar两个版本的下载

    Ibatis,全称为MyBatis,是一个优秀的Java持久层框架,它主要负责简化数据库操作,将SQL语句与Java代码分离,使得开发人员能够更加专注于业务逻辑。在本主题中,我们将深入探讨Ibatis的两个特定版本:ibatis2.3.4.8....

    ibatis-sqlmap-2.3.4.726-sources.jar.zip_birth84v_cutting1v2_ibat

    《深入解析iBatis-SQLMap 2.3.4.726源码》 在Java开发领域,iBatis作为一个优秀的持久层框架,深受广大开发者喜爱。它将SQL语句与Java代码分离,提高了代码的可读性和可维护性。本篇将围绕iBatis-SQLMap 2.3.4.726...

    Manning.iBATIS.in.Action.Jan.2007.eBook-BBL.pdf

    根据提供的文件信息,本书《Manning iBATIS in Action Jan. 2007 eBook-BBL》主要介绍了iBATIS框架的基本概念、安装配置方法、核心功能及其在实际项目中的应用。下面将针对该书籍中提及的主要知识点进行详细阐述。 ...

    ibatis2.3.4.726增删改查源码实例

    在本实例中,"ibatis2.3.4.726增删改查源码实例" 提供了一个完整的基于Ibatis 2.3.4.726版本的开发案例,涵盖了数据库的基本操作,即增(INSERT)、删(DELETE)、改(UPDATE)和查(SELECT)。 首先,我们来了解...

    iBATIS 框架源码剖析.iso

    iBATIS 框架源码剖析.iso 源代码网站版 261 MB

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

    解析这个XML文件的过程涉及到DOM或SAX解析器,源码中这部分功能通常在`org.apache.ibatis.io.Resources`和`org.apache.ibatis.builder.Configuration`类中实现。 三、Executor执行器 Executor执行器是iBatis的核心...

    ibatis-2.3.0.677.zip

    iBATIS,作为Java开发中的一个持久层框架,它的出现极大地简化了数据库操作与应用程序的集成。这个开源项目由Clinton Begin在2001年创立,最初是为了解决密码软件开发中的问题,但随着时间的发展,它逐渐演变成了一...

    ibatis2.3.4.726.jar

    ibatis2.3.4.726.jar ibatis2.3.4.726.jar ibatis2.3.4.726.jar ibatis2.3.4.726.jar

    最稳定Ibatis包 ibatis-2.3.0.677.rar

    Ibatis,一个强大的Java持久层框架,以其轻量级、高度灵活的特点在众多开发者中备受青睐。2.3.0.677是Ibatis的一个重要版本,被誉为“最稳定”的版本,它提供了可靠的性能和稳定性,使得开发人员在处理数据库操作时...

    ibatis-2.3.2.715.jar

    《深入解析ibatis-2.3.2.715.jar》 在Java开发领域,Ibatis作为一个轻量级的持久层框架,以其灵活、易用的特点深受开发者喜爱。本次我们将详细探讨`ibatis-2.3.2.715.jar`这个特定版本的Ibatis库,它为开发者提供了...

    mybatis源码中文注释.zip

    org.apache.ibatis.logging org.apache.ibatis.logging.commons org.apache.ibatis.logging.jdbc org.apache.ibatis.logging.jdk14 org.apache.ibatis.logging.log4j org.apache.ibatis.logging.log4j2 org.apache....

    ibatis-2.3.2.715

    通过分析这份文件,我们可以清晰地知道哪些外部库是iBatis运行所必需的,以便在实际应用中正确配置。 "META-INF"目录下通常包含了项目元数据,如MANIFEST.MF文件,它描述了JAR文件的结构和属性。在这里,我们可以...

Global site tag (gtag.js) - Google Analytics