事務基礎(ACID、隔離級別)請參考:Java 基礎——事務
Spring 以 Bean 形式聲明事務管理器,常用實現:
DataSourceTransactionManager:JDBC / MyBatis 單數據源HibernateTransactionManager:HibernateJtaTransactionManager:分布式事務 (JTA)<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.DriverClass}"/>
<property name="jdbcUrl" value="${jdbc.jdbcUrl}"/>
<property name="user" value="${jdbc.user}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
tx Schema<tx:advice id="txAdvice" transaction-manager="transactionManager"/><aop:config> <aop:pointcut id="bookPointcut" expression="execution(* *.BookServiceImpl.*(..))"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="bookPointcut"/> </aop:config>
注意:只有 public 方法可被增強。
<tx:annotation-driven transaction-manager="transactionManager"/>(若 Bean 名為 transactionManager 可省略屬性)public 方法上加 @Transactional@Service
public class BookServiceImpl {
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public void shop() { ... }
}
Spring 在 JDBC 隔離級別基礎上擴展了 7 種傳播行為:
| 常數 | 行為描述 |
|---|---|
| REQUIRED | 有事務則加入,無則新建(預設) |
| REQUIRES_NEW | 掛起現有事務,強制新建獨立事務 |
| NESTED | 嵌套事務(savepoint),外層回滾則內層回滾,內層回滾不影響外層 |
| SUPPORTS | 有事務則加入,無則以非事務執行 |
| NOT_SUPPORTED | 掛起現有事務,以非事務執行 |
| NEVER | 必須非事務執行,若有事務拋異常 |
| MANDATORY | 必須在現有事務中執行,否則拋異常 |
方法 A 調用方法 B:
- REQUIRED:A、B 共用同一事務(一起提交/回滾)
- REQUIRES_NEW:B 開啟獨立事務,A 失敗不影響 B,B 失敗不影響 A(視配置)
XML 中同樣可配置:
<tx:advice id="bookAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="shop" propagation="REQUIRED" timeout="30" read-only="false" rollback-for="java.lang.Exception"/>
</tx:attributes>
</tx:advice>
@Transactional,配置集中、可讀性高。rollbackFor = Exception.class,避免檢查型異常不回滾。timeout 防止資源佔用過久。readOnly=true。掌握 Spring 事務管理,能從容應對複雜業務的一致性挑戰。