怎么理解 Mybatis 的事務
對于數據庫事務,我們都不陌生,數據庫的事務(Transaction)是數據庫管理系統執行過程中的一個邏輯單位,也是一個不可分割的工作單位。它包含一個或多個SQL語句,這些語句要么全部執行,要么全部不執行。事務是一個原子操作單元,其對數據的修改要么全都執行,要么全都不執行。那么我們就得來看看這個 Mybatis 是怎么處理事務的了。
ACID特性
- 原子性(Atomicity):事務是一個原子操作單元,其對數據的修改要么全都執行,要么全都不執行。
- 一致性(Consistency):事務必須使數據庫從一個一致性狀態變換到另一個一致性狀態。
- 隔離性(Isolation):事務的執行不受其他事務的干擾,事務執行的中間結果對其他事務是不可見的。
- 持久性(Durability):一旦事務提交,則其結果就是永久性的,即使系統發生崩潰,事務執行的結果也不能丟失。
我們通過使用事務,可以確保數據的完整性和一致性,特別是在多個用戶或系統并發訪問和修改數據庫時。如果沒有事務,那么在這些并發操作中可能會出現數據不一致、數據丟失或數據重復等問題。通過使用事務,可以鎖定被修改的數據,直到事務完成并提交,從而確保數據的完整性和一致性。
Mybatis的事務
MyBatis 的事務控制可以從以下幾個方面入手:
(1) 事務管理機制的選擇:MyBatis 提供了兩種主要的事務管理機制,分別是 JDBC 事務管理機制和 MANAGED 事務管理機制。
- JDBC 事務管理機制:這種機制利用 java.sql.Connection 對象來完成對事務的提交(commit())、回滾(rollback())、關閉(close())等操作。MyBatis 框架自身會管理事務,采用原生的 JDBC 代碼去管理事務,如設置 conn.setAutoCommit(false); 來開啟事務,并在業務處理完成后手動提交事務 conn.commit();。
- MANAGED 事務管理機制:在這種機制下,MyBatis 本身不會去實現事務管理,而是讓程序的容器(如 JBOSS、Weblogic)來實現對事務的管理。
(2) 事務的配置:在 MyBatis 的 XML 配置文件中,可以通過節點定義連接某個數據庫的信息,而的 type 屬性決定了使用哪種類型的事務管理機制。例如,將的 type 配置為 "JDBC" 會使用 JDBC 事務管理機制。
(3) 事務工廠的創建:MyBatis 的事務管理依賴于 TransactionFactory 事務工廠的創建。根據的 type 配置和 DataSource 實例,TransactionFactory 會創建一個 Environment 對象,該對象表示一個數據庫的連接,并且會被設置到 Configuration 實例中,以供后續使用。
(4) 業務場景的應用:在實際的業務場景中,如購買操作包含多個執行過程(查詢庫存、下單、更新庫存)或兩個患者賬戶之間的轉賬操作,需要確保這些操作作為一個整體進行,要么全部成功,要么全部失敗并回滾。這時就需要引入事務控制,保證整個操作的有效性。
(5) 事務的邊界管理:合理控制事務的邊界也是非常重要的。過寬的事務邊界可能導致事務執行時間過長,影響系統性能;而過窄的事務邊界則可能導致數據不一致。因此,在設計系統時,需要仔細考慮每個事務的邊界。
(6) 異常處理:在事務執行過程中,如果出現異常,需要根據異常類型和業務需求決定是回滾事務還是進行其他處理。確保在出現異常時能夠正確地處理事務,避免數據的不一致和丟失。
如何設置Mybatis的全局事務
在 MyBatis 中,全局事務的設置通常依賴于底層的數據庫連接池和事務管理器。MyBatis 本身并不直接提供全局事務管理的功能,而是依賴于 JDBC、Spring 或其他容器提供的事務管理機制。下面是一些常見的方法來設置 MyBatis 的全局事務:
1. 使用 JDBC 進行事務管理
如果你的應用沒有使用 Spring 或其他容器,你可以直接使用 JDBC 進行事務管理。在 MyBatis 的配置文件中,你可以將事務管理器設置為 JDBC。
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<!-- 數據庫連接配置 -->
</dataSource>
</environment>
</environments>
<!-- 其他配置 -->
</configuration>
在代碼中,你需要手動管理事務的開啟、提交和回滾。
try (SqlSession session = sqlSessionFactory.openSession()) {
// 開啟事務
Connection conn = session.getConnection();
conn.setAutoCommit(false);
// 執行業務邏輯...
// 提交事務
conn.commit();
} catch (Exception e) {
// 回滾事務
try (Connection conn = session.getConnection()) {
if (!conn.isClosed()) {
conn.rollback();
}
} catch (SQLException ex) {
// 處理異常
}
// 處理異常...
}
2. 使用 Spring 管理 MyBatis 事務
如果你的應用使用了 Spring 框架,那么可以利用 Spring 的聲明式事務管理來管理 MyBatis 的事務。這通常是通過在 Spring 配置文件中配置事務管理器,并在需要事務的方法上使用 @Transactional 注解來實現的。
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<!-- 配置數據源 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<!-- 數據源屬性配置 -->
</bean>
<!-- 配置 SqlSessionFactory -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!-- 其他配置 -->
</bean>
<!-- 配置事務管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 開啟注解事務管理 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
<!-- 其他配置 -->
</beans>
Java 代碼中使用 @Transactional
@Service
public class MyService {
@Autowired
private MyMapper myMapper;
@Transactional
public void myTransactionalMethod() {
// 執行業務邏輯...
myMapper.updateSomeData();
// 如果拋出異常,則事務回滾
}
}
在上面的例子中,@Transactional 注解告訴 Spring 在執行 myTransactionalMethod 方法時應該開啟一個事務。如果方法執行成功,則事務提交;如果方法拋出異常,則事務回滾。
3. 使用其他容器的事務管理
除了 Spring,還有其他一些容器或框架也提供了事務管理的功能,如 Java EE 容器。如果你正在使用這些容器或框架,你可以根據它們的文檔來配置和管理 MyBatis 的事務。
- 確保你的數據庫連接池支持事務。大多數現代連接池(如 HikariCP、c3p0、DBCP 等)都支持事務。
- 在使用 Spring 或其他容器管理事務時,確保你的 MyBatis Mapper 接口或實現類被正確地掃描和注冊為 Spring Bean。
- 在使用 @Transactional 注解時,注意其傳播行為(propagation behavior)、隔離級別(isolation level)等屬性的設置,以滿足你的業務需求。
所以,你對Mybatis的事務了解了么?