(一)事务配置

在Mybatis的配置文件中可以配置事务管理方式如下:

<?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
 <configuration>
     <environments default="development">
          <environment id="development">
              <!--配置事务的管理方式-->
              <transactionManager type="JDBC" />
              <!-- 配置数据库连接信息 -->
              <dataSource type="POOLED">
                  <property name="driver" value="com.mysql.jdbc.Driver" />
                 <property name="url" value="jdbc:mysql://localhost:3306/mybatis" />
                 <property name="username" value="root" />
                 <property name="password" value="root" />
             </dataSource>
         </environment>
     </environments>    
 </configuration>

说明:
(1)type为"JDBC"时,使用JdbcTransaction管理事务。
(2)type为"managed"时,使用ManagedTransaction管理事务(也就是交由外部容器管理)

(二)事务工厂:

mybatis的事务是由TransactionFactory创建的,利用典型的简单工厂模式来创建Transaction,如下图:
transaction-factory.jpg

说明:
Transaction:封装事务管理方法的接口
TransactionFactory:抽象事务工厂生产方法
JdbcTransactionFactory:实现TransactionFactory接口,用于生产JdbcTransaction的工厂类
ManagedTransactionFactory:实现TransactionFactory接口,用于生产ManagedTransaction的工厂类
JdbcTransaction:实现Transaction接口,只是对事务进行了一层包装、实际调用数据库连接Connection的事务管理方法
ManagedTransaction:实现Transaction没有对数据库连接做任何事务处理、交由外部容器管理

(三)源码分析:

第一步:解析配置文件的transactionManager节点。

private void environmentsElement(XNode context) throws Exception {
          //只关注事务部分...
          TransactionFactory txFactory = transactionManagerElement(child.evalNode("transactionManager"));
          ...
  }
  
private TransactionFactory transactionManagerElement(XNode context) throws Exception {
    if (context != null) {
      String type = context.getStringAttribute("type");
      Properties props = context.getChildrenAsProperties();
      TransactionFactory factory = (TransactionFactory) resolveClass(type).newInstance();
      factory.setProperties(props);
      return factory;
    }
    throw new BuilderException("Environment declaration requires a TransactionFactory.");
  }

注意:两种事务工厂已经在mybatis初始化的时候完成了注册:
typeAliasRegistry.registerAlias("JDBC", JdbcTransactionFactory.class);
typeAliasRegistry.registerAlias("MANAGED", ManagedTransactionFactory.class);

第二步:利用反射机制生成具体的的factory,此处以JdbcTransactionFactory为例,查看一下JdbcTransactionFactory的源码:

public class JdbcTransactionFactory implements TransactionFactory {

  public void setProperties(Properties props) {
  }

  public Transaction newTransaction(Connection conn) {
    return new JdbcTransaction(conn);
  }

  public Transaction newTransaction(DataSource ds, TransactionIsolationLevel level, boolean autoCommit) {
    return new JdbcTransaction(ds, level, autoCommit);
  }
}

说明:
在反射过程中,JdbcTransactionFactory默认无参构造方法被调用

第三步:获取具体类型的事务,以JdbcTransaction为例。

public Transaction newTransaction(Connection conn) {
    return new JdbcTransaction(conn);
  }

说明:
JdbcTransaction是通过Connection来创建具体的实例

第四步:事务的底层实现。以JdbcTransaction为例来说明。

public class JdbcTransaction implements Transaction {

  private static final Log log = LogFactory.getLog(JdbcTransaction.class);

  protected Connection connection;
  protected DataSource dataSource;
  protected TransactionIsolationLevel level;
  protected boolean autoCommmit;

  public JdbcTransaction(DataSource ds, TransactionIsolationLevel desiredLevel, boolean desiredAutoCommit) {
    dataSource = ds;
    level = desiredLevel;
    autoCommmit = desiredAutoCommit;
  }

  public JdbcTransaction(Connection connection) {
    this.connection = connection;
  }

  public Connection getConnection() throws SQLException {
    if (connection == null) {
      openConnection();
    }
    return connection;
  }

  public void commit() throws SQLException {
    if (connection != null && !connection.getAutoCommit()) {
      connection.commit();
    }
  }

  public void rollback() throws SQLException {
    if (connection != null && !connection.getAutoCommit()) {
      connection.rollback();
    }
  }

  public void close() throws SQLException {
    if (connection != null) {
      resetAutoCommit();
      if (log.isDebugEnabled()) {
        log.debug("Closing JDBC Connection [" + connection + "]");
      }
      connection.close();
    }
  }

  protected void setDesiredAutoCommit(boolean desiredAutoCommit) {
    try {
      if (connection.getAutoCommit() != desiredAutoCommit) {
       
        connection.setAutoCommit(desiredAutoCommit);
      }
    } catch (SQLException e) {
      throw new TransactionException("Error configuring AutoCommit.  "
          + "Your driver may not support getAutoCommit() or setAutoCommit(). "
          + "Requested setting: " + desiredAutoCommit + ".  Cause: " + e, e);
    }
  }

  protected void resetAutoCommit() {
    try {
      if (!connection.getAutoCommit()) {
        connection.setAutoCommit(true);
      }
    } catch (SQLException e) {
      log.debug("Error resetting autocommit to true "
          + "before closing the connection.  Cause: " + e);
    }
  }

  protected void openConnection() throws SQLException {
    connection = dataSource.getConnection();
    if (level != null) {
      connection.setTransactionIsolation(level.getLevel());
    }
    setDesiredAutoCommit(autoCommmit);
  }
}

从源码中可知,JdbcTransaction如何管理事务的,是通过封装调用DataSource获取connection来实现的。

标签: none

《收徒公告》已经3人报名,还差2人,报名截止日期:2018年12月15日,请移步:>>>>>>

添加新评论