mybatis源碼分析(2)——事務概述


這篇文章主要對mybatis中的事務做一簡單的分析,幫助讀者理清一些概念。

先來看看在JAVA事務的相關技術,在JAVA中有兩類事務,JDBC事務和JTA事務,如果是JDBC類型的事務,則是由Connection類來控制的。如果創建一個Connection對象時,沒有顯示調用

setTransactionIsolation(int level) 方法,則Connection使用當前數據庫默認的事務隔離級別,數據庫的默認事務隔離級別可以通過相應的SQL語句進行查詢,例如在Mysql數據庫下可使用 select @@tx_isolation;語句查看當前數據庫的事務隔離級別。

JDBCConnection類針對事務的隔離性定義了五個隔離級別。

Connection.TRANSACTION_NONE

Connection.TRANSACTION_READ_COMMITTED

Connection.TRANSACTION_READ_UNCOMMITTED

Connection.TRANSACTION_REPEATABLE_READ

Connection.TRANSACTION_SERIALIZABLE

 

在mybatis中,有一個事務管理器的配置,其中type屬性可以配置事務的類型,提供了JDBCMANAGED的配置屬性,這就說明在mybatis中事務的管理方式有兩個事務管理器的實現,都是針對JDBC事務的事務管理器(非JTA事務),分別是:

  org.apache.ibatis.transaction.jdbc.JdbcTransaction

  org.apache.ibatis.transaction.managed.ManagedTransaction

這兩個類都實現了org.apache.ibatis.transaction.Transaction接口,Transaction接口定義了如下方法:

 

   Connection getConnection() throws SQLException;
   void commit() throws SQLException;
   void rollback() throws SQLException;
   void close() throws SQLException;

 

 

 

通過這些方法可以看出這個接口實際是對Connection類進行了包裝,包括了Connection的創建、提交、回滾、關閉動作。並且,其中ManagedTransaction類的commit方法和rollback方法中沒有做任何事,也就是說這個類是不控制事務的提交和回滾的,而交由外部容器去管理事務的提交與回滾,外部容器(可以是Spring 容器或EJB容器)通過聲明式事務的方式進行管事。

 

mybatis中,通過一個Enumorg.apache.ibatis.session.TransactionIsolationLevel

 

來定義了事務的隔離級別:

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

TransactionIsolationLevel類中定義的事務隔離級別其實就是引用了Connection類中的事務隔離級別,下面分別對這幾種隔離級別進行說明: 

TRANSACTION_NONE:表示不支持事務的常量

TRANSACTION_READ_UNCOMMITTED:表示可以發生臟讀 (dirty read)、不可重復讀和虛讀 (phantom read) 的常量

TRANSACTION_READ_COMMITTED:不可重復讀和虛讀可以發生

TRANSACTION_REPEATABLE_READ:虛讀可以發生

TRANSACTION_SERIALIZABLE:指示不可以發生臟讀、不可重復讀和虛讀的常量。

再來理解下什么是臟讀、不能重復讀、虛讀(又叫幻讀)

臟讀:如果一個事務對數據進行了更新,但事務還沒有提交,另一個事務就可以“看到”該事務沒有提交的更新結果。這樣造成的問題是,如果第一個事務回滾,那么第二個事務在此之前所“看到”的數據就是一筆臟數據。

不可重復讀:指同個事務在整個事務過程中對同一筆數據進行讀取,每次讀取結果都不同。如果事務1在事務2的更新操作之前讀取一次數據,在事務2的更新操作之后再讀取同一筆數據一次,兩次結果是不同的。所以TRANSACTION_READ_COMMITTED是無法避免不可重復讀和虛讀。

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

 

最后再總結下:mybatis只是對JDBC事務提供了事務管理器的封裝,如果想在mybatis中使用JTA事務,需要我們自行實現org.apache.ibatis.transaction.Transaction接口,對此Spring框架提供了解決方案,可能通過mybatis+spring+atomikos的整合來完成。或者采用EJB容器也可以提供JTA事務的支持。關於具體整合方案,可關注我的后續文章。

注:Atomikos 是一款 Java/JTA 事務處理工具,其官網需翻牆才能訪問。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM