1、MyBatis事务配置

在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管理事务(也就是交由外部容器管理)

2、MyBatis事务工厂

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

transaction-factory.jpg

说明:

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

3、MyBatis事务源码分析

第一步:解析配置文件的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
{

    /* 连接**/
    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();

            //关闭连接
            connection.close();
        }
    }

    protected void setDesiredAutoCommit(boolean desiredAutoCommit)
    {
        try
        {
            //事务提交状态不一致时修改
            if (connection.getAutoCommit() != desiredAutoCommit)
            {
                connection.setAutoCommit(desiredAutoCommit);
            }
        }
        catch (SQLException e)
        {
            throw new TransactionException("Error configuring AutoCommit.", e);
        }
    }

    protected void resetAutoCommit()
    {
        try
        {
            if (!connection.getAutoCommit())
            {

                connection.setAutoCommit(true);
            }
        }
        catch (SQLException e)
        {

        }
    }

    protected void openConnection() throws SQLException
    {

        connection = dataSource.getConnection();
        if (level != null)
        {
            connection.setTransactionIsolation(level.getLevel());
        }
        setDesiredAutoCommit(autoCommmit);
    }

}

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

标签: none

添加新评论