Mybatis学习笔记-事务管理详解

本文详细探讨了Mybatis的事务管理体系,包括JDBC和MANAGED两种事务类型。在JDBC模式下,Mybatis直接使用JDBC进行事务控制;而在MANAGED模式下,通常与Spring集成,事务管理交由Spring负责。Mybatis通过TransactionFactory和Transaction接口创建并管理事务,如JdbcTransaction和ManagedTransaction。当设置为MANAGED时,DML操作的事务将由外部容器管理。
摘要由CSDN通过智能技术生成

Mybatis作为最流行的持久层框架,当然支持事务的统一管理。
不多说,先来张图热热场…
这里写图片描述
该图大致概括了mybatis的事务体系。

  • mybatis事务的分类
    1)JDBC :直接简单使用了JDBC 的提交和回滚设置。
    2)MANAGED:这个配置几乎没做什么。它从来不提交或回滚一个连接,通常情况下,在mybatis与spring集成时这样设置,因为spring提供了同意的事务管理,mybatis在事务上不需要做任何事情。

  • 配置mybatis事务管理器
    在mybatis核心配置文件中

<environments default="mysql_environment">
        <environment id="mysql_environment">
        <!-- 配置mybatis的事务 -->
            <transactionManager type="JDBC" />
            <dataSource type="POOLED">
        <property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/test" />
                <property name="username" value="zhangdd" />
                <property name="password" value="zd1991.." />
            </dataSource>
        </environment>
</environments> 

其中<transactionManager/>节点指定了事务管理器的类型,该节点只有一个type属性。

  • mybatis创建事务
    应用启动时,mybatis会加载核心配置文件,当加载到<environments/>节点时,会根据<transactionManager/><dataSource>来创建一个Environment对象:
    public Environment(String id, TransactionFactory transactionFactory, DataSource dataSource) {,从这个构造器签名中我们可以看到,事务(Transaction)是由事务工厂(TransactionFactory)创建的。

创建事务与创建数据源类似,TransactionFactory是事务工程的顶级接口,其下有两个实现类:JdbcTransactionFactoryManagedTransactionFactory,mybatis根据<transactionManager/>的type属性来选择用哪种工厂类创建事务。

JDBC Transaction是创建如下:
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);
  }
}

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()) {
      if (log.isDebugEnabled()) {
        log.debug("Committing JDBC Connection [" + connection + "]");
      }
      connection.commit();
    }
  }
  public void rollback() throws SQLException {
    if (connection != null && !connection.getAutoCommit()) {
      if (log.isDebugEnabled()) {
        log.debug("Rolling back JDBC Connection [" + connection + "]");
      }
      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) {
        if (log.isDebugEnabled()) {
          log.debug("Setting autocommit to " + desiredAutoCommit + " on JDBC Connection [" + connection + "]");
        }
        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()) {
        if (log.isDebugEnabled()) {
          log.debug("Resetting autocommit to true on JDBC Connection [" + connection + "]");
        }
        connection.setAutoCommit(true);
      }
    } catch (SQLException e) {
      log.debug("Error resetting autocommit to true "
          + "before closing the connection.  Cause: " + e);
    }
  }
  protected void openConnection() throws SQLException {
    if (log.isDebugEnabled()) {
      log.debug("Openning JDBC Connection");
    }
    connection = dataSource.getConnection();
    if (level != null) {
      connection.setTransactionIsolation(level.getLevel());
    }
    setDesiredAutoCommit(autoCommmit);
  }
}

很显然,JdbcTransaction是通过底层的Connection对象来管理事务的。

ManagedTransactionFactory:

public class ManagedTransactionFactory implements TransactionFactory {

  private boolean closeConnection = true;

  public void setProperties(Properties props) {
    if (props != null) {
      String closeConnectionProperty = props.getProperty("closeConnection");
      if (closeConnectionProperty != null) {
        closeConnection = Boolean.valueOf(closeConnectionProperty);
      }
    }
  }
  public Transaction newTransaction(Connection conn) {
    return new ManagedTransaction(conn, closeConnection);
  }
  public Transaction newTransaction(DataSource ds, TransactionIsolationLevel level, boolean autoCommit) {
    return new ManagedTransaction(ds, level, closeConnection);
  }
}

ManagedTransaction:

public class ManagedTransaction implements Transaction {

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

  private DataSource dataSource;
  private TransactionIsolationLevel level;
  private Connection connection;
  private boolean closeConnection;

  public ManagedTransaction(Connection connection, boolean closeConnection) {
    this.connection = connection;
    this.closeConnection = closeConnection;
  }
  public ManagedTransaction(DataSource ds, TransactionIsolationLevel level, boolean closeConnection) {
    this.dataSource = ds;
    this.level = level;
    this.closeConnection = closeConnection;
  }

  public Connection getConnection() throws SQLException {
    if (this.connection == null) {
      openConnection();
    }
    return this.connection;
  }
  public void commit() throws SQLException {
    // Does nothing
  }
  public void rollback() throws SQLException {
    // Does nothing
  }
  public void close() throws SQLException {
    if (this.closeConnection && this.connection != null) {
      if (log.isDebugEnabled()) {
        log.debug("Closing JDBC Connection [" + this.connection + "]");
      }
      this.connection.close();
    }
  }
  protected void openConnection() throws SQLException {
    if (log.isDebugEnabled()) {
      log.debug("Openning JDBC Connection");
    }
    this.connection = this.dataSource.getConnection();
    if (this.level != null) {
      this.connection.setTransactionIsolation(this.level.getLevel());
    }
  }
}

从上面的代码中可以提炼出最重要的几行:

public void commit() throws SQLException {
    // Does nothing
  }
  public void rollback() throws SQLException {
    // Does nothing
  }

是的,就想你看到的那样,commit()rollback()什么都没有做。
当将事务类型配置成Managed时,mybatis所有的DML操作都将失效,事务会交由spring或web容器统一管理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值