`
田智伟
  • 浏览: 206507 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

ibatis源码学习--ibatis-dao

阅读更多

ibatis的包组成中从历史版本中我们能看到他是有:ibatis-dao.jar,ibatis-common.jar,ibatis-sqlmap.jar三个包组成,所以学习源码之前,我们先澄清一些东西,同时让大家弄清楚什么时候该引入什么包,一般情况下如果你的项目只是用到了ibatis,没有其他容器使用,那么你可以考虑使用ibatis-dao+ibatis-common+ibatis-sqlmap,如果你使用了spring做为容器,那么其实你将不需要引入ibatis-dao,同时有时候我们也会发现有ibatis-core的包,这个是在ibatis的2.2以后将ibatis-common.jar和ibatis-sqlmap.jar二合一之后的结果,所以看到ibatis-core之后基本就不需要引入common和sqlmap这两个包了,如果你引入了ibatis-dao.jar那么ibatis-core是必须引入的。

 

这里就需要弄明白为什么会有ibatis-dao.jar,为什么2.3.x的版本中不在引入。这都要从ibatis-dao.jar的功能及设计初衷谈起。

 

首先DAO是J2EE的一种设计模式即DAO设计模式,ibatis-dao.jar的存在是更面向应用层的,SQL Map组件相对要更底层一些,靠近数据源层,DAO组件可以通过调用SQL Map组件来实现业务处理,ibatis提供的DAO层不但可以继承Ibatis的SQLMap组件想成一个一个一体的解决方案,同时还可以融入其他多种ORM组件,如Hibernate、Apache Ojb、TopLink、甚至包括JDBC、JTA。

在我们检出的jpetstore项目中我们会看到一个类DaoConfig

 

public class DaoConfig {

  private static final String resource = "com/ibatis/jpetstore/persistence/dao.xml";
  private static final DaoManager daoManager;

  static {
    try {
      daoManager = newDaoManager(null);
      Properties props = Resources.getResourceAsProperties("properties/database.properties");
      String url = props.getProperty("url");
      String driver = props.getProperty("driver");
      String username = props.getProperty("username");
      String password = props.getProperty("password");
      if (url.equals("jdbc:hsqldb:mem:jpetstore")) {
        Class.forName(driver).newInstance();
        Connection conn = DriverManager.getConnection(url, username, password);
        try {
          ScriptRunner runner = new ScriptRunner(conn, false, false);
          runner.setErrorLogWriter(null);
          runner.setLogWriter(null);
          runner.runScript(Resources.getResourceAsReader("ddl/hsql/jpetstore-hsqldb-schema.sql"));
          runner.runScript(Resources.getResourceAsReader("ddl/hsql/jpetstore-hsqldb-dataload.sql"));
        } finally {
          conn.close();
        }
      }
    } catch (Exception e) {
      throw new RuntimeException("Description.  Cause: " + e, e);
    }

  }

  public static DaoManager getDaoManager() {
    return daoManager;
  }

  public static DaoManager newDaoManager(Properties props) {
    try {
      Reader reader = Resources.getResourceAsReader(resource);
      return DaoManagerBuilder.buildDaoManager(reader, props);
    } catch (Exception e) {
      throw new RuntimeException("Could not initialize DaoConfig.  Cause: " + e, e);
    }
  }

} 

 

其中

 

 public static DaoManager newDaoManager(Properties props) {
    try {
      Reader reader = Resources.getResourceAsReader(resource);
      return DaoManagerBuilder.buildDaoManager(reader, props);
    } catch (Exception e) {
      throw new RuntimeException("Could not initialize DaoConfig.  Cause: " + e, e);
    }
  }
 

 

上面的代码加载了一个resource,这个resource正是一个名字叫dao.xml的文件

文件内容大致如下:

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE daoConfig
    PUBLIC "-//ibatis.apache.org//DTD DAO Configuration 2.0//EN"
    "http://ibatis.apache.org/dtd/dao-2.dtd">

<daoConfig>

  <context>

    <transactionManager type="SQLMAP">
      <property name="SqlMapConfigResource"
        value="com/ibatis/jpetstore/persistence/sqlmapdao/sql/sql-map-config.xml"/>
    </transactionManager>

    <dao interface="com.ibatis.jpetstore.persistence.iface.ItemDao"
      implementation="com.ibatis.jpetstore.persistence.sqlmapdao.ItemSqlMapDao"/>

    <dao interface="com.ibatis.jpetstore.persistence.iface.SequenceDao"
      implementation="com.ibatis.jpetstore.persistence.sqlmapdao.SequenceSqlMapDao"/>

    <dao interface="com.ibatis.jpetstore.persistence.iface.AccountDao"
      implementation="com.ibatis.jpetstore.persistence.sqlmapdao.AccountSqlMapDao"/>

    <dao interface="com.ibatis.jpetstore.persistence.iface.CategoryDao"
      implementation="com.ibatis.jpetstore.persistence.sqlmapdao.CategorySqlMapDao"/>

    <dao interface="com.ibatis.jpetstore.persistence.iface.ProductDao"
      implementation="com.ibatis.jpetstore.persistence.sqlmapdao.ProductSqlMapDao"/>

    <dao interface="com.ibatis.jpetstore.persistence.iface.OrderDao"
      implementation="com.ibatis.jpetstore.persistence.sqlmapdao.OrderSqlMapDao"/>

  </context>

</daoConfig>

 这个文件就是ibatis-dao.jar的入口文件,也是核心文件,后续的所有操作将依照这个文件进行。在此向置于文件头,后续会多次用到

 

在ibatis-dao.jar包中我们可以看到他有两个子包组成分别为:client、engine.共计34个类

1.client主要作为对外的接口部分。

2.engine主要是其内部实现。

client中包含:5个类(或接口)一个子包(包含6个类/接口)

Dao类:该类是一个接口,只是一个表示接口,没有任何约束,主要用来表述所有实现该接口的类都是操作数据的类,ibatis DAO中的所有业务dao类都要事先client中的Dao接口

DaoException类:该类继承RuntimeException类,用来统一异常输出

DaoManager类:核心接口,用来定义所有管理ibatis的dao对象实现必须遵守的规则,包括获取dao实现类,获取事务,以及事务的打开、提交、关闭

DaoManagerBuilder类:该类用来创建DaoManager类,但其本身不做处理,通过传入配置文件生成DaoManager,具体实现还是需要调用engine包下的XmlDaoManagerBuilder,XmlDaoManagerBuilder功能就是将dao.xml文件实例化成client中的的各个实例对象,是DaoManager类的工厂类。

DaoTransaction类:统一的事务操作接口

client包下还有一个template包,该包中的类都是根据模版原则,定义了不同orm的DAO操作规范

DaoTemplate,一个实现了Dao的抽象类

HibernateDaoTemplate.java :针对Hibernate定义的Dao模板类

JdbcDaoTemplate.java:JDBC定义的Dao的简单封装

OjbBrokerDaoTemplate.java

SqlMapDaoTemplate.java

ToplinkDaoTemplate.java

 

engine下的文件包含三部分:build ,负责通过解析dao.xml(可以为别的名字,跟DaoManager最终加载的文件名同名即可)文件生成client中的实例对象;impl组件,为build组件提供支持,用来将build中解析的字符串封装成impl中的实例,impl是client的具体实现。transaction负责集中ORM的事务管理。

首先介绍build,build中包含两个类:

DaoClasspathEntityResolver.java:实现了org.xml.sax.EntityResolver,作为自定义的xml解析器,负责从ClassPath中加载DTD文件,同时将其作为流输出,后续再解析dao.xml中需要。

XmlDaoManagerBuilder.java:该类主要用来解析dao.xml生成impl中的对象,也是ibatis-dao.xml的核心类

下面介绍 impl部分:

impl部分主要包含:

DaoContext.java :这个类是用来封装上面dao.xml中的context节点的实现类

DaoImpl.java:这个类是用来封装context节点下的所有dao节点的实现类

DaoProxy.java:负责创建Dao接口的代理对象。

DaoTransactionState.java:事务的状态信息,内部实现采用自关联

StandardDaoManager.java:ibatis-dao的管理类。idContextMap属性用来按照context的id存放所有的context实例,typeContextMap用来存放key为daoimpl的实现类接口,value为dao归属的context的实现类;daoImplMap包含两种key-value组合:key:负责存放有daoImpl的代理类,value:daoimpl,key:dao实现类的实例;

 

所有的操作都起始于DaoManagerBuilder的buildDaoManager的方法,最终调用new XmlDaoManagerBuilder().buildDaoManager(reader, props);加载dao.xml并解析,获取到创建imp下的所有实例并组装,在ibatis-dao中所有数据库操作都是源于transaction,其中包含6中事务类型,根据自己的实际需要使用,这个也决定了最终你的配置文件中<transactionManager type="JDBC">这个节点的type属性是什么目前ibatis-dao支持的类型有:见XmlDaoManagerBuilder类构造函数

 

 public XmlDaoManagerBuilder() {
    typeAliases.put("EXTERNAL", ExternalDaoTransactionManager.class.getName());
    typeAliases.put("HIBERNATE", HibernateDaoTransactionManager.class.getName());
    typeAliases.put("JDBC", JdbcDaoTransactionManager.class.getName());
    typeAliases.put("JTA", JtaDaoTransactionManager.class.getName());
    typeAliases.put("OJB", "com.ibatis.dao.engine.transaction.ojb.OjbBrokerTransactionManager");
    typeAliases.put("SQLMAP", SqlMapDaoTransactionManager.class.getName());
    typeAliases.put("TOPLINK", "com.ibatis.dao.engine.transaction.toplink.ToplinkDaoTransactionManager");
  }

 

 所以也就出现了上边dao.xml文件中的SQLMAP,这个最终是在该构造函数中匹配到了SqlMapDaoTransactionManager.class.getName()该类,所以如果你定义了这里没有的,那么可能就需你使用全限定名了

同时ibatis-dao中用到了很多ibatis-common.jar中的工具类,如Resource,这个是主要是获取文件转换为inputStream或者转为Reader,加载类,实例化类,ClassInfo,ibatis中很强大的一个类,后边在介绍common包的时候会单独介绍。

至此dao包就基本讲完了,没有大篇幅的介绍代码主要是我比较懒,同时内容太多容易让人生烦,而且也容易跑题,所以就不一一介绍了,但是34个类的功能基本清楚了,具体的实现进一步去看问题应该就不大了。之所以将这个包主要出于一下目的:

1.平时我们经常看到很多人用spring直接使用了sqlmapclient,却还要去加载dao包,这就是没有弄明白dao包的作用。

2.从dao的实现我们略微可以收获一下结论,简单容器的实现,如context的实现,该包后续没有发展,估计也有一部分原因是因为spring的强大(我意淫的),使作者放弃了继续搞的打算,不过我还是觉得对于业务调用来说,早期的dao还是很方便了,即便你有多个数据源,只需要配置多个context便可以了,对于业务调用他只要从DaoManager中get就好了,不用管底层到底调用了那个数据源,这一点我觉得还是很有必要的。

3.dao的包装类,daoimpl很有想法,通过代理来操作事务,隐藏了很多操作,简化了开发

4.xml文档的解析可以看看XmlDaoManagerBuilder这个类,虽然代码比较多,不过结构很清晰,而且从第一行看到最后一行也绝对不会混乱,因为代码就是从上到下实现的。

 

 

这里我们整理一下两个过程

1.文件解析及其加载的过程:

一、客户端调用XmlDaoManagerBuilderde.buildDaoManager方法

二、XmlDaoManagerBuilder对象创建一个StandardDaoManager对象

三、读取配置文件中的daoConfig节点下的context个数,XmlDaoManagerBuilder对象循环创建1个或者多个DaoContext对象

四、根据配置文件中的context节点下transactionManager的个数,XmlDaoManagerBuilder对象创建TransactionManager对象

五、把Transaction对象赋值给DaoContext对象,由于DaoContext对象只有一个Transaction属性,所以如果配置文件配置多个TransactionManager最后只能是最后一个有效

六、根据context节点下DAO的个数XmlDaoManagerBuilder对象实例化多个DaoImpl对象

七、每个DaoImpl实例化对象根据获得的dao节点中的implementation属性采用constructor.newInstance方法动态实例化dao的的实现类赋值给daoImpl.setDaoInstance(dao);

八、调用daoImpl的// 生成dao的代理 daoImpl.initProxy();赋值给impl的proxy属性最终作为DaoManager的get参数被使用,从而保证调用到的是代理后的daoimpl,可以达到隐藏调用transaction的效果

九、将所有的daoImpl加入到DaoContext的Map中

十、将所有的DaoContext遍历加入到StandardDaoManager对象的Map变量中,同时将所有的DaoImpl放入到StandardDaoManager的Map属性中,具体参加文章上部分标红内容

十一、XmlDaoManagerBuilder返回获取到的StandardDaoManager对象。

 

2.Dao的调用过程:

一、客户端调用某个实现了Dao的类

二、通过DaoManager获取到的是DaoImpl的代理类,所以调用其invoke方法

三、DaoProxy对象的invoke方法执行过程通过DaoImpl获取StandardDaoManager对象 

四、判断是否启用了transaction,执行五、六、七,跳过后续,否则执行以下所有

五、如果启用了,则获取DaoImpl的DaoContext对象

六、通过DaoContext开启事务:context.startTransaction();

七、执行Impl中的方法,method.invoke(daoImpl.getDaoInstance(), args);

八、context.commitTransaction();

九、context.endTransaction();

 

 

关于xml文件的解析分为两种

 

  1. SAX基于事件流的解析
  2. DOM基于XML文档树结构的解析

在对dao.xml的解析中,采用了二者结合的方式。对于dao.xml的格式是否正确,这里采用的是DTD文件,它包括一些常用的xml语法规则,如:XML文档必须有根元素、XML文档必须关闭等等。这些校验规则需要通过SAX的EnityResolver接口的实现类来处理的,比如本包中的DaoClasspathEntityResolver。

 

 

Ok,本篇文章就到这里。

在这里

感谢ibatis官方的无私

感谢《IBATIS框架源码剖析》作者

 

 

 

 

 

 

 

分享到:
评论

相关推荐

    iBATIS-DAO-2.3.4.726.rar_com.ibatis.dao_iBATIS dao 2_iBatis DAO_

    总的来说,iBATIS DAO 2.3.4.726版的源码分析对于学习和理解Java中的持久层设计有极大的帮助。通过阅读和理解源码,开发者不仅能掌握iBATIS DAO的基本使用,还能深入了解其内部实现,提升数据库操作的技巧和优化能力...

    iBATIS3学习--Demo

    在学习iBATIS时,理解这些数据库表的结构对于更好地掌握映射和查询的实现至关重要。 通过这个“Demo”,学习者可以了解到以下知识点: 1. **iBATIS框架的基本架构**:包括SqlSessionFactory,SqlSession,Mapper...

    ibatis源码

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

    ibatis jar文件

    3. ibatis-core-3.0-sources:这个文件包含的是3.0版本iBATIS核心库的源代码,对于开发者来说,查看源码有助于理解和学习内部工作原理。 4. ibatis-dao-2:可能是指iBATIS Data Access Object (DAO)的第二个版本,...

    iBATIS_DBL-2.2.0.638.zip_iBATIS_DBL_ibatis_ibatis 2_ibatis2 src_

    这个压缩包提供了对iBatis 2.x版本的深入理解,特别是对于那些希望查看或学习iBatis 2.2.0.638源码的开发者来说,极具价值。 首先,让我们深入了解iBatis的核心概念。iBatis的主要功能是作为一个SQL映射框架,它将...

    iBATIS2.3.4 jar包及源码

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

    iBATIS框架源码剖析源码

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

    ibatisDao.rar

    本资料“ibatisDao.rar”包含了一份对iBATIS DAO框架的深入分析,旨在帮助开发者更好地理解和应用这一技术。 在iBATIS中,DAO(Data Access Object)是数据库访问对象,它封装了对数据库的增删查改操作。DAO模式是...

    iBATIS&Spring合奏(一)--DAO

    标题中的“iBATIS&Spring合奏(一)--DAO”指的是在Java开发中,将iBATIS和Spring框架结合使用来实现数据访问层(DAO)的一种技术整合。iBATIS是一个优秀的持久层框架,它允许开发者将SQL语句直接写在配置文件中,提供...

    ibatis学习资料汇总

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

    ibatis SQL映射文件、DAO、model自动生成工具源码

    这个"ibatis SQL映射文件、DAO、model自动生成工具"的源码,旨在简化开发过程,通过自动化生成基本的Ibatis相关代码,提高开发效率。 首先,SQL映射文件(Mapper XML)是Ibatis的核心部分,它定义了数据库操作的SQL...

    ibatis 框架源码剖析 书籍源代码 带有详尽注释

    7. DAO(数据访问对象):DAO层是iBATIS在应用中的常见使用模式,它封装了与数据库的交互逻辑,提供了一组接口供业务层调用,将数据操作与业务逻辑解耦。 8. MyBatis:iBATIS在2010年停止开发,随后发展成为MyBatis...

    ibatis2.3.4.726增删改查源码实例

    总的来说,这个"Ibatis2.3.4.726增删改查源码实例"为你提供了一个完整的Ibatis应用示例,你可以通过阅读源代码学习如何配置Ibatis,如何编写Mapper接口和XML文件,以及如何在Java代码中调用Ibatis进行数据库操作。...

    最新的ibatis 3.0(包含源码)

    总之,Ibatis 3.0提供了一套强大且灵活的SQL映射框架,通过源码学习,我们可以深入了解其内部工作原理,更好地利用其特性来提高开发效率。同时,面对兼容性问题,我们需要灵活应对,寻找最佳解决方案。

    java8源码-simple-ibatis:手写mybatis框架---思路变成实践

    在学习mybatis源码时,有感而发。耗时3周左右,基本满足了一些常用的Sql操作本项目所涉及的代码都是个人所写,没有一句copy,肯定不是很完善,大家理解下,后续有时间会一直更新。如果你对源码感兴趣,也可以加入...

    iBATIS3 GA.源码,含案列

    2. **DAO模式支持**: iBATIS3提供了一套完整的DAO实现,使得开发者可以轻松地创建数据访问层,减少了大量重复代码。 3. **分离关注点**: SQL逻辑与业务逻辑分离,使得代码更易于维护和测试。SQL在配置文件中定义,...

    struts2+spring2+ibatis集成

    3. **DAO与iBatis**:Spring2配置文件中会包含iBatis的配置,定义SqlSessionFactory和Mapper接口,通过MyBatis的SqlSession执行SQL语句,实现数据访问。 4. **结果映射**:Struts2的结果类型可以配置为Spring的...

    spring+ibatis的Java项目demo项目源码

    本项目源码提供了一个完整的 Spring + iBATIS 的 Demo 示例,旨在帮助开发者理解和学习如何将这两个框架集成到一个Java项目中。下面将详细介绍这个项目的相关知识点。 **Spring 框架** Spring 是一个全面的后端开发...

    struts2 spring ibatis 项目整合源码

    在项目源码中,"ibatis"这个文件可能包含了iBatis的相关配置文件(如sqlmap-config.xml)、映射文件(*.xml)以及数据访问接口(DAO)的实现类。这些文件定义了如何与数据库进行交互,包括SQL查询语句、参数映射和...

    struts1.2 spring2 ibatis 集成项目实战源码

    在这个项目实战源码中,我们可以深入学习这三大框架如何协同工作,以及如何在实际开发中应用它们。 首先,Struts1.2是一个基于MVC(Model-View-Controller)设计模式的开源框架,它主要用于处理HTTP请求和控制应用...

Global site tag (gtag.js) - Google Analytics