Transaction management of Mybatis source code analysis

 

1. Introduction

1. Transaction characteristics (ACID)

(1) Atomicity

All operations in a transaction are either completed or not done, and there can be no intermediate state. If an exception occurs during the execution of a transaction, the completed operation will be rolled back, so that all operations remain in the state of not doing all

(2) Consistency

The integrity constraints of the database before and after the execution of the transaction have not changed, and are in a consistent state before and after the execution.
For example, if A transfers money to B, the transfer is a transaction. No matter how many times the transfer is made, the total amount of the accounts of A and B is the same.

(3) Isolation

Affairs and affairs are isolated from each other and do not affect each other.

(4) Durability

After the transaction is completed, the changes to the data in the database are permanent.

2. Concurrency of transactions

(1) Dirty read

Dirty read means transaction A reads uncommitted data of transaction B.

(2) Non-repeatable reading

Non-repeatable read means that two identical query operations in the same transaction read different data. For example, between two query operations of transaction A, transaction B modifies and commits the data.

(3) Phantom reading

A phantom read means that transaction A submits an update operation, and at this time transaction B inserts a new piece of data. After transaction A looks at the data, it will find that there is a piece of data that has not been updated, as if an illusion has occurred.

Non-repeatable reads and phantom reads are both a transaction A reads the data after transaction B commits, and a dirty read means that transaction A reads data that transaction B did not commit.
Non-repeatable reading is somewhat similar to phantom reading, which is prone to confusion. Non-repeatable read focuses on the modification operation of another transaction, and phantom read focuses on the addition and deletion operations of another transaction. Non-repeatable reads avoid the need for row locks, and phantom reads require table locks.

3. Transaction isolation level

Transaction isolation level

Second, the configuration of the transaction

1. Configuration of transaction node

The transaction transaction is configured through the transaction node of the configuration file. Like the data source node, it is a child node of the environment node, such as:

<environments default="test">
  <environment id="test">
	 <transactionManager type="JDBC"></transactionManager>
	 <dataSource type="UNPOOLED">
	      <property name="driver" value="${driver-class-name}"/>
	      <property name="url" value="${url}"/>
	      <property name="username" value="${username}"/>
	      <property name="password" value="${password}"/>
	 </dataSource>
  </environment>
</environments>
参考自http://www.mybatis.org/mybatis-3/zh/configuration.html#environments
在 MyBatis 中有两种类型的事务管理器(也就是 type=”[JDBC|MANAGED]”):
JDBC – 这个配置就是直接使用了 JDBC 的提交和回滚设置,它依赖于从数据源得到的连接来管理事务作用域。
MANAGED – 这个配置几乎没做什么。它从来不提交或回滚一个连接,而是让容器来管理事务的整个生命周期(比如 JEE 应用服务器的上下文)。 默认情况下它会关闭连接,然而一些容器并不希望这样,因此需要将 closeConnection 属性设置为 false 来阻止它默认的关闭行为。例如:
<transactionManager type="MANAGED">
  <property name="closeConnection" value="false"/>
</transactionManager>

2. Analysis of transaction node

Similarly, according to the previous blogs, the analysis of the configuration file is carried out in the XMLConfigBuilder#parse() method, and the analysis of the transaction node is entrusted to the XMLConfigBuilder#transactionManagerElement(XNode) method.

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.");
}

Find the TransactionFactory type of the object according to the type attribute, and call the parameterless constructor to generate the TransactionFactory object.

Three, transaction management

1. Class diagram

Transaction class diagram
Mybatis itself does not handle affairs, but just makes a layer of encapsulation, which is convenient to call.

1. TransactioIsolationLevel

TransactionIsolationLeve is the transaction isolation level of Mybatis. There are 5 out of Mybatis, NONE means no transaction is supported, and the other 4 have a one-to-one correspondence with the database transaction isolation level.

public enum TransactionIsolationLevel {
  NONE(Connection.TRANSACTION_NONE),
  READ_COMMITTED(Connection.TRANSACTION_READ_COMMITTED),
  READ_UNCOMMITTED(Connection.TRANSACTION_READ_UNCOMMITTED),
  REPEATABLE_READ(Connection.TRANSACTION_REPEATABLE_READ),
  SERIALIZABLE(Connection.TRANSACTION_SERIALIZABLE);

  private final int level;

  private TransactionIsolationLevel(int level) {
    this.level = level;
  }

  public int getLevel() {
    return level;
  }
}

2. JdbcTransaction

JdbcTransaction is the transaction processed by jdbc, there is a connection object to complete the commit, rollback and close of the transaction.

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

@Override
public void rollback() throws SQLException {
  if (connection != null && !connection.getAutoCommit()) {
    if (log.isDebugEnabled()) {
      log.debug("Rolling back JDBC Connection [" + connection + "]");
    }
    connection.rollback();
  }
}

@Override
public void close() throws SQLException {
  if (connection != null) {
    resetAutoCommit();
    if (log.isDebugEnabled()) {
      log.debug("Closing JDBC Connection [" + connection + "]");
    }
    connection.close();
  }
}
protected void resetAutoCommit() {
  try {
    if (!connection.getAutoCommit()) {
      // MyBatis does not call commit/rollback on a connection if just selects were performed.
      // Some databases start transactions with select statements
      // and they mandate a commit/rollback before closing the connection.
      // A workaround is setting the autocommit to true before closing the connection.
      // Sybase throws an exception here.
      if (log.isDebugEnabled()) {
        log.debug("Resetting autocommit to true on JDBC Connection [" + connection + "]");
      }
      connection.setAutoCommit(true);
    }
  } catch (SQLException e) {
    if (log.isDebugEnabled()) {
      log.debug("Error resetting autocommit to true "
        + "before closing the connection.  Cause: " + e);
    }
  }
}

As you can see, the connection is set to automatically submit in the close method.

3. ManagedTransaction

ManagedTransaction allows the container to manage the entire life cycle of the transaction. Using the commit and rollback functions of ManagedTransaction will not have any impact on the transaction. It will do nothing. It transfers the power of transaction management to the container for implementation.

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

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

@Override
public void close() throws SQLException {
  if (this.closeConnection && this.connection != null) {
    if (log.isDebugEnabled()) {
      log.debug("Closing JDBC Connection [" + this.connection + "]");
    }
    this.connection.close();
  }
}
  •  

Guess you like

Origin blog.csdn.net/qq_33762302/article/details/115340030