ibatis-dao框架中相关实例域存在原因总结

有关ibatis-dao组件部分的框架剖析和业务流程在《iBATIS 框架源码剖析》一书中写的已经比较详细。具体内容就不在这里写出来了,今天就把自己看过之后的几条心得和分析跟大家分享一下。写的不是很全,但都是个人觉得对于整体理解有很大帮助的内容。

1. daoManager提供的需求:
    ·根据接口来获得实例化对象的代理对象——getDao方法实现。理由显而易见,必须获得代理对象来调用相关方法。
    ·根据实例化对象或代理对象获得事务——getTransaction方法实现impl.getDaoContext().getTransaction()。理由见第四点


2. daoManager提供事务方法的原因(start,commit,end)
    可以实现多个context同时提交事务。
    为此:有了连个ThreadLocal变量。transactionMode和contextInTransactionList
    transactionMode:用于记录否开启事务
    contextInTransactionList:存多个context到Arraylist中,不存入相同的context


实例:
情况一:
前提为同一线程下
一个context包含两个dao:daoProxy1,daoProxy2
那么,
//daoManager.startTransaction()开启事务
//daoProxy1.insert();会触发invoke,然后context.start
//daoProxy2.insert();会触发invoke,然后context.start。本来两个start与与下面的一次commit不对应会出现异常,但Context采用单例事务启动,如下
//daoManager.commitTransaction()只提交一个context即context.commitTransaction
//daoManager.endTransaction()只提交一个context即context.endTransaction

context中单例事务提交
//采用单例模式实现事务
  public void startTransaction() {
    if (state.get() != DaoTransactionState.ACTIVE) {//因此,相同的context只会start一次,因而与commit一次同步
      DaoTransaction trans = transactionManager.startTransaction();
      transaction.set(trans);
      state.set(DaoTransactionState.ACTIVE);
      daoManager.addContextInTransaction(this);
    }
  }
=> state参数的必要性
private ThreadLocal state = new ThreadLocal();// 处理事务状态信息的本地线程

情况二:
一个context1包含1个dao:daoProxy1。一个context2包含1个dao:daoProxy2
那么:
//daoManager.startTransaction()开启事务
//daoProxy1.insert();会触发invoke,然后context1.start
//daoProxy2.insert();会触发invoke,然后context2.start
//daoManager.commitTransaction()遍历所有context,全部提交context1.commitTransaction,context2.commitTransaction
//daoManager.endTransaction()同样end两次
=>保证start,commit,end一一对应


3. 解析dao.xml时就已经确定了DaoTransactionManager对象。所以,context.startTransaction()中
DaoTransaction trans = transactionManager.startTransaction();将会new出一个具体的事务对象如SQLMap
  public DaoTransaction startTransaction() {
    return new SqlMapDaoTransaction(client);继续调用client.startTransaction()这属于底层启动事务
  }
其中 client对象是解析sqlmap-config.xml得到的对象。
client = SqlMapClientBuilder.buildSqlMapClient(reader, properties);属于SQLMap组件部分


4. 就SQLMap实现而言,由于所有基本的数据库操作都基于client对象,而client对象在SqlMapDaoTransaction中有,故提供一个方法getSqlMap()来获得

client:
SqlMapDaoTemplate:为对外、面向用户的模板类,用户继承它后,需要使用client来实现相关CRUD操作,所以实现了一个方法
  protected SqlMapExecutor getSqlMapExecutor() {
    SqlMapDaoTransaction trans = (SqlMapDaoTransaction) daoManager.getTransaction(this);
    return trans.getSqlMap();
  }
这个方法可以获得client对象。而daoManager是肯定可以获得,因此,要实现daoManager.getTransaction方法,参数是实例化对象或代理。
  public DaoTransaction getTransaction(Dao dao) {
    DaoImpl impl = (DaoImpl) daoImplMap.get(dao);
    return impl.getDaoContext().getTransaction();
  }
=>该方法应运而生=>daoImplMap内置对象要实现


写的比较粗糙,希望对那些看过源码的同学有所有帮助。有什么错误之处,也请大家积极指正。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值