mybatis原始碼解讀:transaction包(事務管理功能)
技術標籤:mybaits原始碼mybatis原始碼
歡迎關注本人公眾號:
mybatis的transaction包是負責進行事務管理的包,該包內包含2個子包:jdbc子包中包含基於jdbc進行事務管理的類,managed子包中包含基於容器進行事務管理的類。
1.事務概述
事務即資料庫事務,是資料庫執行過程中的一個邏輯單元。事務有以下4個特性:
Atomicity(原子性):事務必須被作為一個整體執行,要麼全部執行, 要麼全部不執行。不允許只執行其中的一部分。
Consistency(一致性):事務應該保證資料庫從一致性狀態轉換到另一個一致性狀態。一致性狀態是指資料庫中資料的完整性約束。
Isolation(隔離性):多個事務併發執行時, 事務不會互相干擾。
Durability(永續性):一旦事務提交,則其所做的修改就會永久儲存到資料庫中。
2.事務介面及工廠
整個transaction包採用了工廠方法模式實現,TransactionFactory是所有事務工廠的介面。
public interface TransactionFactory {
/**
* 配置工廠的屬性
* @param props 工廠的屬性
*/
default void setProperties(Properties props) {
// NOP
}
/**
* 從給定的連線中獲取一個事務
* @param conn 給定的連線
* @return 獲取的事務物件
*/
TransactionnewTransaction(Connectionconn);
/**
* 從給定的資料來源中獲取事務,並對事務進行一些配置
* @param dataSource 資料來源
* @param level 資料隔離級別
* @param autoCommit 是否自動提交事務
* @return 獲取的事務物件
*/
Transaction newTransaction(DataSource dataSource, TransactionIsolationLevel level, boolean autoCommit);
}
Transaction是所有事務的介面。
public interface Transaction {
/**
* 獲取該事務對應的資料庫連線
* @return 資料庫連線
* @throws SQLException
*/
Connection getConnection() throws SQLException;
/**
* 提交事務
* @throws SQLException
*/
void commit() throws SQLException;
/**
* 回滾事務
* @throws SQLException
*/
void rollback() throws SQLException;
/**
* 關閉對應的資料連線
* @throws SQLException
*/
void close() throws SQLException;
/**
* 讀取設定的事務超時時間
* @return 事務超時時間
* @throws SQLException
*/
Integer getTimeout() throws SQLException;
}
TransactionFactory介面與Transaction介面都有2套實現,分別在jdbc包和managed包中。
3.jdbc事務
jdbc包中存放的是實現jdbc事務的JdbcTransaction類及其對應的工廠類,
JdbcTransaction類是jdbc事務的管理類,具體的事務操作是由JdbcTransaction類直接呼叫Connection類提供的事務方法來完成的。
public class JdbcTransaction implements Transaction {
private static final Log log = LogFactory.getLog(JdbcTransaction.class);
// 資料庫連線
protected Connection connection;
// 資料來源
protected DataSource dataSource;
// 事務隔離級別
protected TransactionIsolationLevel level;
// 是否自動提交事務
protected boolean autoCommit;
public JdbcTransaction(DataSource ds, TransactionIsolationLevel desiredLevel, boolean desiredAutoCommit) {
dataSource = ds;
level = desiredLevel;
autoCommit = desiredAutoCommit;
}
/**
* 提交事務
* @throws SQLException
*/
@Override
public void commit() throws SQLException {
// 連線存在且不會自動提交事務
if (connection != null && !connection.getAutoCommit()) {
if (log.isDebugEnabled()) {
log.debug("Committing JDBC Connection [" + connection + "]");
}
// 呼叫connection物件的方法提交事務
connection.commit();
}
}
/**
* 回滾事務
* @throws SQLException
*/
@Override
public void rollback() throws SQLException {
if (connection != null && !connection.getAutoCommit()) {
if (log.isDebugEnabled()) {
log.debug("Rolling back JDBC Connection [" + connection + "]");
}
connection.rollback();
}
}
}
JdbcTransactionFactory類負責生產JdbcTransaction物件。
public class JdbcTransactionFactory implements TransactionFactory {
@Override
public Transaction newTransaction(Connection conn) {
return new JdbcTransaction(conn);
}
@Override
public Transaction newTransaction(DataSource ds, TransactionIsolationLevel level, boolean autoCommit) {
return new JdbcTransaction(ds, level, autoCommit);
}
}
4.容器事務
managed包中存放的是實現容器事務的ManagedTransaction類及其對應的工廠類。
在ManagedTransaction類中可以看到commit,rollback等方法內都沒有任何邏輯操作,這是因為相關的事務操作都委託給了容器進行管理。
public class ManagedTransaction implements Transaction {
private static final Log log = LogFactory.getLog(ManagedTransaction.class);
// 資料來源
private DataSource dataSource;
// 事務隔離級別
private TransactionIsolationLevel level;
// 資料庫連線
private Connection connection;
// 是否關閉資料庫連線
private final boolean closeConnection;
/**
* 提交事務
* @throws SQLException
*/
@Override
public void commit() throws SQLException {
// Does nothing
}
/**
* 回滾事務
* @throws SQLException
*/
@Override
public void rollback() throws SQLException {
// Does nothing
}
}
比如mybatis和spring整合時,mybatis中拿到的資料庫連線物件是spring提供的。spring可以通過xml配置,註解等多種方式來管理事務(即決定事務何時開始,提交,回滾)。當然,這種情況下,事務的最終實現也是由Connection物件的相關方法實現的。整個過程中,mybatis不需要處理任何事務操作,全都委託給spring即可。