mybatis源碼分析之事務管理器 原

上一篇:mybatis源碼分析之Configuration

主要分析了構建SqlSessionFactory的過程中配置文件的讀取.

這次重點分析mybatis的事務管理器

仍舊從官網給的例子着手分析,配置文件mybatis-config.xml

<?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="${driver}"/>
            <property name="url" value="${url}"/>
            <property name="username" value="${username}"/>
            <property name="password" value="${password}"/>
          </dataSource>
        </environment>
      </environments>
      <mappers>
        <mapper resource="org/mybatis/example/BlogMapper.xml"/>
      </mappers>
  </configuration>

 

在根結點configuration下有environments和mappers兩個結點.

environments:環境,mybatis可以配置多個環境即可以將 SQL 映射應用於多種數據庫之中.如開發,測試,生產對應不同的數據庫.

mappers:映射器,提供映射文件的地址.

在environment下的transactionManager就是現在要重點分析的對象.

mybatis中有兩種類型的事務管理器,JDBC和MANAGED.

JDBC:直接使用了 JDBC 的提交和回滾設置,它依賴於從數據源得到的連接來管理事務範圍。

MANAGED:不提交或回滾一個連接,而是讓容器來管理事務的整個生命週期。

對例子進行分析,之前分析過

String resource = "org/mybatis/example/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

 

現在再來分析

SqlSession session = sqlSessionFactory.openSession();

DefaultSqlSessionFactory裏的openSession

public SqlSession openSession() {
  return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
}

 

openSessionFromDataSource

private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
  Transaction tx = null;
  try {
    //根據配置獲取環境
    final Environment environment = configuration.getEnvironment();
    //構建事務工廠
    final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
    //通過事務工廠創建事務
    tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
    final Executor executor = configuration.newExecutor(tx, execType);
    return new DefaultSqlSession(configuration, executor, autoCommit);
  } catch (Exception e) {
    closeTransaction(tx); // may have fetched a connection so lets call close()
    throw ExceptionFactory.wrapException("Error opening session.  Cause: " + e, e);
  } finally {
    ErrorContext.instance().reset();
  }
}

 

看一下各個類之間的關係

JdbcTransaction和ManagedTransaction對應事務管理器的兩種類型JDBC和MANAGED.

由於ManagedTransaction幾乎沒做什麼,所以重點分析JdbcTransaction.

因爲JdbcTransaction直接使用了 JDBC 的提交和回滾設置,它依賴於從數據源得到的連接來管理事務範圍。

那麼直接來看看JDBC的事務

java.sql.Connection

/**
 * A constant indicating that transactions are not supported.
 */
int TRANSACTION_NONE             = 0;

/**
 * A constant indicating that
 * dirty reads, non-repeatable reads and phantom reads can occur.
 * This level allows a row changed by one transaction to be read
 * by another transaction before any changes in that row have been
 * committed (a "dirty read").  If any of the changes are rolled back,
 * the second transaction will have retrieved an invalid row.
 */
int TRANSACTION_READ_UNCOMMITTED = 1;

/**
 * A constant indicating that
 * dirty reads are prevented; non-repeatable reads and phantom
 * reads can occur.  This level only prohibits a transaction
 * from reading a row with uncommitted changes in it.
 */
int TRANSACTION_READ_COMMITTED   = 2;

/**
 * A constant indicating that
 * dirty reads and non-repeatable reads are prevented; phantom
 * reads can occur.  This level prohibits a transaction from
 * reading a row with uncommitted changes in it, and it also
 * prohibits the situation where one transaction reads a row,
 * a second transaction alters the row, and the first transaction
 * rereads the row, getting different values the second time
 * (a "non-repeatable read").
 */
int TRANSACTION_REPEATABLE_READ  = 4;

/**
 * A constant indicating that
 * dirty reads, non-repeatable reads and phantom reads are prevented.
 * This level includes the prohibitions in
 * <code>TRANSACTION_REPEATABLE_READ</code> and further prohibits the
 * situation where one transaction reads all rows that satisfy
 * a <code>WHERE</code> condition, a second transaction inserts a row that
 * satisfies that <code>WHERE</code> condition, and the first transaction
 * rereads for the same condition, retrieving the additional
 * "phantom" row in the second read.
 */
int TRANSACTION_SERIALIZABLE     = 8;

 

事務隔離級別

TRANSACTION_NONE:不支持事務

TRANSACTION_READ_UNCOMMITTED:允許髒讀、不可重複的讀和虛讀.

TRANSACTION_READ_COMMITTED:不允許髒讀,允許不可重複的讀和虛讀.

TRANSACTION_REPEATABLE_READ:不允許髒讀和不可重複的讀,允許虛讀.

TRANSACTION_SERIALIZABLE:不允許髒讀、不可重複的讀和虛讀.

髒讀:一個事務對數據進行更新,但事務還沒有提交,另一個事務就可以取到該事務沒有提交的更新結果。

不可重複讀:同一個事務在整個事務過程中對同一筆數據進行多次讀取,每次讀取結果都不同。

虛讀:同一個查詢在整個事務過程中多次執行後,查詢所得的結果集是不一樣的。虛讀針對的是多條記錄。

不可重複讀:列值的不同; 虛讀:記錄數量的不同。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章