Mybatis 事务源码分析

Mybatis是一个支持自定义SQL语句,存储过程,高级映射的数据持久化框架。

 

它封装了JDBC,在框架中隐藏了几乎所有的JDBC的API,这里说下从源码的角度Mybatis 3.x (笔者用的是3.2.8)是如何封装JDBC来实现事务处理的。

 

回忆下mybatis是怎么使用事务管理的,session.commit(),session.rollback(), JDBC呢,是connection.commit(),connection.rollback()。所以这篇文章的内容就变成了如何从session.commit()到connection.commit()。

 

首先从session来看看,我们获得一个session对象其实是DefaultSqlSession对象,这个类中的commit() 方法如下。

 

 public void commit() {
    commit(false);
  }

  public void commit(boolean force) {
    try {
      executor.commit(isCommitOrRollbackRequired(force));
      dirty = false;
    } catch (Exception e) {
      throw ExceptionFactory.wrapException("Error committing transaction.  Cause: " + e, e);
    } finally {
      ErrorContext.instance().reset();
    }
  }

 private boolean isCommitOrRollbackRequired(boolean force) {
    return (!autoCommit && dirty) || force;
  }

 

 

然后到CachingExecutor 中的方法

 

public void commit(boolean required) throws SQLException {
    delegate.commit(required);
    tcm.commit();
  }

//也许对这执行commit的对象不熟悉,看下面
private Executor delegate;
private TransactionalCacheManager tcm = new TransactionalCacheManager();

 

  所以真正我们关心的事务是另外一个Executor,BaseExecutor中commit()方法

public void commit(boolean required) throws SQLException {
    if (closed) throw new ExecutorException("Cannot commit, transaction is already closed");
    clearLocalCache();
    flushStatements();
    if (required) {
      transaction.commit();
    }
  }

 前面两个方法是跟缓存相关,只有最后一个才是我们关心的,JDBCTransaction类中的commit()

 public void commit() throws SQLException {
    if (connection != null && !connection.getAutoCommit()) {
      if (log.isDebugEnabled()) {
        log.debug("Committing JDBC Connection [" + connection + "]");
      }
      connection.commit();
    }
  }

 现在我们明白了,JDBCTransaction中包装了一个connection的对象。这也是我们在使用mybatis配置文件时设置的事务管理类。

<environments default="development">
  <environment id="development">
    <transactionManager type="JDBC"> <!--这里-->
      <property name="..." value="..."/>
    </transactionManager>
    <dataSource type="POOLED">
      <property name="driver" value="${driver}"/>
      <property name="url" value="${url}"/>
      <property name="username" value="${username}"/>
      <property name="password" value="${password}"/>
    </dataSource>
  </environment>
</environments>

 

 

 

 

 

 

 

你可能感兴趣的:(Mybatis 事务源码分析)