Spring05——Spring 如何實現事務管理


在此之前,我們已經了解了 Spring 相關的基礎知識,今天將為給位帶來,有關 Spring 事務代理的相關知識。關注我的公眾號「Java面典」,每天 10:24 和你一起了解更多 Java 相關知識點。

事務管理方式

在 Spring 項目中,我們可以用通過四種方式實現事務管理,分別是 編程式事務管理、基於 TransactionProxyFactoryBean的聲明式事務管理、基於 @Transactional 的聲明式事務管理 和 基於Aspectj AOP配置事務。其實現方式如下:

編程式事務管理

// JDBC 事務管理
Connection connection = DriverManager.getConnection("connUrl", "username", "password");
//關閉自動提交,此句代碼會自動開啟事務。默認為true,自動提交。
connection.setAutoCommit(false);  

String sql1 = "insert into user(name) values (?)";
PreparedStatement preparedStatement1 = connection.prepareStatement(sql1);
preparedStatement1.setString(1,"Java面典");
preparedStatement1.executeUpdate(); 

String sql2 = "update user set name=? where id=?";
PreparedStatement preparedStatement2 = connection.prepareStatement(sql2);
preparedStatement2.setString(1, "Java面典 new");
preparedStatement2.setInt(2, 10);
preparedStatement2.executeUpdate();  

try{
     //提交事務
    connection.commit();  
}catch (SQLException e){
    //失敗就回滾
    connection.rollback();  
} finally {
    preparedStatement1.close();
    preparedStatement2.close();
    connection.close();
}

基於 TransactionProxyFactoryBean的聲明式事務管理

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">
	
	<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>

基於 @Transactional 的聲明式事務管理

@Service
public class UserServiceImpl implements IUserService {
    
    @Transactional(transactionManager = "transactionManager", rollbackFor = Exception.class)
    @Override
    public void add(User user) {
        // todo 
    }
}

基於Aspectj AOP配置事務

<!-- 事務管理器 -->
<bean id="tracnsactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"></property>
</bean>
    
<tx:advice id="txAdvice" transaction-manager="myTracnsactionManager">
    <tx:attributes>
        <!-- 為連接點指定事務屬性 -->
        <tx:method name="add*" isolation="DEFAULT" propagation="REQUIRED"/>
        <tx:method name="stockChange" isolation="DEFAULT" propagation="REQUIRED" rollback-for="StockException"/>
    </tx:attributes>
</tx:advice>
    
<aop:config>
    <!-- 切入點配置 -->
    <aop:pointcut expression="execution(* *..service.*.*(..))" id="point"/>
    <aop:advisor advice-ref="txAdvice" pointcut-ref="point"/>
</aop:config>

事務傳播機制

Spring 的事務傳播分為以下幾個機制:

  • REQUIRED:如果有事務則加入事務,如果沒有事務,則創建一個新的(默認值);

  • NOT_SUPPORTED:Spring 不為當前方法開啟事務,相當於沒有事務;

  • REQUIRES_NEW:不管是否存在事務,都創建一個新的事務,原來的方法掛起,新的方法執行完畢后,繼續執行老的事務;

  • MANDATORY:必須在一個已有的事務中執行,否則報錯;

  • NEVER:必須在一個沒有的事務中執行,否則報錯;

  • SUPPORTS:如果其他 bean 調用這個方法時,其他 bean 聲明了事務,則就用這個事務,如果沒有聲明事務,那就不用事務;
    SUPPORTS類型的事務傳播機制,是否使用事務取決於調用方法是否有事務,如果有則直接用,如果沒有則不使用事務。

  • NESTED:如果當前存在事務,則在嵌套事務內執行。如果當前沒有事務,則執行與 REQUIRED 類似的操作;

注意事項

在 A 方法內,調用 B 方法時,存在以下規則:

  1. REQUIRED
    當兩個方法的傳播機制都是 REQUIRED 時,如果一旦發生回滾,兩個方法都會回滾;
  2. REQUIRES_NEW
    當 A 方法傳播機制為 REQUIRES_NEW ,會開啟一個新的事務,並單獨提交方法,所以 B 方法的回滾並不影響 A 方法事務提交;
  3. NESTED
    當 A 方法為 REQUIRED,B 方法為 NESTED 時,A 方法開啟一個嵌套事務;
    當 A 方法回滾時,B 方法也會回滾;反之,如果 B 方法回滾,則並不影響 A 方法的提交。

事務隔離級別

TransactionDefinition 接口中定義了五個表示隔離級別的常量:

  • ISOLATION_DEFAULT:使用后端數據庫默認的隔離界別,MySQL默認采用的REPEATABLE_READ 隔離級別,Oracle 默認采用的 READ_COMMITTED 隔離級別;

  • ISOLATION_READ_UNCOMMITTED:最低的隔離級別,允許讀取,允許讀取尚未提交的的數據變更,可能會導致臟讀、幻讀或不可重復讀;

  • ISOLATION_READ_COMMITTED:允許讀取並發事務已經提交的數據,可以阻止臟讀,但是幻讀或不可重復讀仍有可能發生;

  • ISOLATION_REPEATABLE_READ:對同一字段的多次讀取結果都是一致的,除非數據是被本身事務自己所修改,可以阻止臟讀和不可重復讀,但幻讀仍有可能發生;

  • ISOLATION_SERIALIZABLE:最高的隔離級別,完全服從 ACID 的隔離級別。所有的事務依次逐個執行,這樣事務之間就完全不可能產生干擾,也就說,該級別可以阻止臟讀、不可重復讀以及幻讀。但是這將嚴重影響程序的性能。通常情況下也不會用到該級別。

Spring 系列推薦

Spring04——Spring MVC 全解析

Spring03——有關於 Spring AOP 的總結

Spring02——Spring 中 Bean 的生命周期及其作用域

Spring01——你應該了解的,有關 IOC 容器的一切


免責聲明!

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



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