Mybatisソースコード分析のトランザクション管理

 

1.はじめに

1.トランザクション特性(ACID)

(1)アトミシティ

トランザクション内のすべての操作は完了しているか完了しておらず、中間状態になることはありません。トランザクションの実行中に例外が発生した場合、実行された操作はロールバックされるため、すべての操作はすべてを実行していない状態のままになります。

(2)一貫性

トランザクションの実行前後のデータベースの整合性制約は変更されておらず、実行の前後で一貫した状態にあります。
たとえば、AがBに送金する場合、送金はトランザクションです。送金が何度行われても、AとBの口座の合計金額は同じです。

(3)分離

事務と事務は互いに分離されており、互いに影響を及ぼしません。

(4)耐久性

トランザクションが完了した後、データベース内のデータへの変更は永続的です。

2.トランザクションの並行性

(1)ダーティリード

ダーティリードとは、トランザクションAがトランザクションBのコミットされていないデータを読み取ることを意味します。

(2)繰り返し不可の読み

繰り返し不可の読み取りとは、同じトランザクション内の2つの同一のクエリ操作が異なるデータを読み取ることを意味します。たとえば、トランザクションAの2つのクエリ操作間で、トランザクションBはデータを変更してコミットします。

(3)ファントムリーディング

ファントム読み取りとは、トランザクションAが更新操作を送信し、この時点でトランザクションBが新しいデータを挿入することを意味します。トランザクションAがデータを確認した後、次のように、更新されていないデータがあることがわかります。幻想が起こった場合。

繰り返し不可能な読み取りとファントム読み取りはどちらも、トランザクションAがトランザクションBのコミット後にデータを読み取ることであり、ダーティ読み取りは、トランザクションAがトランザクションBがコミットしなかったデータを読み取ることを意味します。
繰り返し不可能な読み方は、混乱しがちな幻の読み方にいくぶん似ています。繰り返し不可の読み取りは、別のトランザクションの変更操作に焦点を合わせ、ファントム読み取りは、別のトランザクションの追加および削除操作に焦点を合わせます。繰り返し不可能な読み取りは行ロックの必要性を回避し、ファントム読み取りはテーブルロックを必要とします。

3.トランザクション分離レベル

トランザクション分離レベル

次に、トランザクションの構成

1.トランザクションノードの構成

トランザクショントランザクションは、構成ファイルのトランザクションノードを介して構成されます。データソースノードと同様に、次のような環境ノードの子ノードです。

<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.トランザクションノードの分析

同様に、以前のブログによると、構成ファイルの分析はXMLConfigBuilder#parse()メソッドで実行され、トランザクションノードの分析はXMLConfigBuilder#transactionManagerElement(XNode)メソッドに委託されます。

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

type属性に従ってオブジェクトのTransactionFactoryタイプを検索し、パラメーターなしのコンストラクターを呼び出してTransactionFactoryオブジェクトを生成します。

3、トランザクション管理

1.クラス図

トランザクションクラス図
Mybatis自体は問題を処理しませんが、カプセル化のレイヤーを作成するだけで、呼び出すのに便利です。

1. TransactioIsolationLevel

TransactionIsolationLeveは、Mybatisのトランザクション分離レベルです。Mybatisには5つあり、NONEはトランザクションがサポートされていないことを意味し、他の4つはデータベーストランザクション分離レベルと1対1で対応しています。

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は、jdbcによって処理されるトランザクションであり、トランザクションのコミット、ロールバック、およびクローズを完了するための接続オブジェクトがあります。

@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);
    }
  }
}

ご覧のとおり、接続はcloseメソッドで自動的に送信するように設定されています。

3. ManagedTransaction

ManagedTransactionを使用すると、コンテナはトランザクションのライフサイクル全体を管理できます。ManagedTransactionのコミットおよびロールバック機能を使用しても、トランザクションに影響はありません。何もしません。トランザクション管理の機能をコンテナに転送して実装します。

@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();
  }
}
  •  

おすすめ

転載: blog.csdn.net/qq_33762302/article/details/115340030
おすすめ