命名空間引入
<beans xmlns="https://www.springframework.org/schema/beans"
xmlns:tx="https://www.springframework.org/schema/tx"
xmlns:aop="https://www.springframework.org/schema/aop"
xsi:schemaLocation="...
https://www.springframework.org/schema/tx https://www.springframework.org/schema/tx/spring-tx.xsd
https://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
單數據源事務配置
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
多数據源/多事務管理器配置
<bean id="txManager1" class="...DataSourceTransactionManager">
<property name="dataSource" ref="ds1"/>
<qualifier value="tx1"/>
</bean>
<bean id="txManager2" class="...DataSourceTransactionManager">
<property name="dataSource" ref="ds2"/>
<qualifier value="tx2"/>
</bean>
<tx:annotation-driven transaction-manager="txManager1"/> <!-- 默認 -->
@Transactional 使用規範
- 標註位置:建議標註在實現類/實現方法上,而非接口(註解不可繼承,基於接口代理才生效)。
- 方法可見性:僅
public 方法生效;protected/private/package-private 不會啟動事務(Spring AOP 基於代理,內部調用不經代理)。
- 指定事務管理器:
@Transactional("tx1") 或 @Transactional(value="tx1") 使用 qualifier 或 bean 名稱匹配。
核心屬性詳解
| 屬性 | 說明 | 默認值 |
| propagation | 傳播行為 | REQUIRED |
| isolation | 隔離級別 | DEFAULT (數據庫默認) |
| timeout | 超時秒數 | -1 (無超時) |
| readOnly | 只讀優化 | false |
| rollbackFor | 觸發回滾的異常類 | RuntimeException, Error |
| noRollbackFor | 不回滾的異常類 | 空 |
高頻失效場景(必讀)
- 內部方法調用:
methodA() 調用 this.methodB(),methodB 上的 @Transactional 不生效(繞過代理)。
解決:將 methodB 移至另一 Bean,或注入自身 @Autowired SelfService self 調用 self.methodB()。
- 非 public 方法:
@Transactional private void foo() 不生效。
- 異常被捕獲未重拋:
try {…} catch (Exception e) { log.error } 事務不回滾。需重拋或手動 TransactionAspectSupport.currentTransactionStatus().setRollbackOnly()。
- 事務管理器與數據源不匹配:方法操作
ds1,但指定 @Transactional("txManager2")(綁定 ds2),事務不生效。
- 默認事務管理器變更:新增數據源導致加載順序變化,默認事務管理器漂移。強制建議:始終顯式指定
@Transactional("txManagerName")。
傳播行為速查
REQUIRED:有事務加入,無則新建(最常用)。
REQUIRES_NEW:掛起當前事務,新建獨立事務(獨立提交/回滾)。
NESTED:嵌套事務(Savepoint),外層回滾內層必回滾,內層回滾外層可選擇提交。
NOT_SUPPORTED:以非事務方式運行,掛起當前事務。
最佳實踐清單
- 服務層方法加
@Transactional,DAO 層不加。
- 只讀查詢添加
readOnly=true。
- 業務異常繼承
RuntimeException 或配置 rollbackFor。
- 避免大事務:將非事務邏輯(外部 API 調用、文件操作、耗時計算)移出事務邊界。
- 整合測試驗證回滾:
@Transactional @Rollback @Test。