MyBatis 事务源码分析
先來看看在JAVA事務的相關技術,在JAVA中有兩類事務,JDBC事務和JTA事務,如果是JDBC類型的事務,則是由Connection類來控制的。如果創建一個Connection對象時,沒有顯示調用
setTransactionIsolation(int?level)?方法,則Connection使用當前數據庫默認的事務隔離級別,數據庫的默認事務隔離級別可以通過相應的SQL語句進行查詢,例如在Mysql數據庫下可使用?select?@@tx_isolation;語句查看當前數據庫的事務隔離級別。
JDBC的Connection類針對事務的隔離性定義了五個隔離級別。
Connection.TRANSACTION_NONE
Connection.TRANSACTION_READ_COMMITTED
Connection.TRANSACTION_READ_UNCOMMITTED
Connection.TRANSACTION_REPEATABLE_READ
Connection.TRANSACTION_SERIALIZABLE
在mybatis中,有一個事務管理器的配置,其中type屬性可以配置事務的類型,提供了JDBC或MANAGED的配置屬性,這就說明在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中,通過一個Enum類org.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事務的支持。
轉載于:https://www.cnblogs.com/wl0000-03/p/6443900.html
總結
以上是生活随笔為你收集整理的MyBatis 事务源码分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Codeforces Round #40
- 下一篇: 我国油气领域获重大突破:“地下珠峰”已找