在 TransactionProxyFactoryBean 或父類 Bean 中定義:
<property name="transactionAttributes">
<props>
<prop key="insert*">PROPAGATION_REQUIRED,-Exception</prop>
<prop key="update*">PROPAGATION_REQUIRED,-Exception</prop>
<prop key="delete*">PROPAGATION_REQUIRED,-Exception</prop>
<prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
</props>
</property>
格式:方法名模式=傳播行為,隔離級別,只讀標誌,超時,回滾異常規則
| 常量 | 行為描述 | 典型場景 |
|---|---|---|
| PROPAGATION_REQUIRED | 支持當前事務,無則新建(最常用) | 通用業務方法 |
| PROPAGATION_SUPPORTS | 支持當前事務,無則非事務執行 | 純查詢、只讀操作 |
| PROPAGATION_MANDATORY | 必須在事務中執行,無則拋異常 | 強制事務上下文的核心邏輯 |
| PROPAGATION_REQUIRES_NEW | 掛起當前事務,新建獨立事務 | 日誌記錄、審計、獨立提交 |
| PROPAGATION_NOT_SUPPORTED | 非事務執行,掛起當前事務 | 長耗時非事務操作、外部 API 呼叫 |
| PROPAGATION_NEVER | 非事務執行,有事務則拋異常 | 嚴禁事務的場景 |
| PROPAGATION_NESTED | 嵌套事務(需 JDBC 3.0+ 驅動支援) | 部分回滾、保存點管理 |
-Exception:遇到 Exception(含子類)回滾,+Exception 表示提交readOnly:標註只讀,數據庫可優化鎖策略,Hibernate 可跳過髒檢查timeout_30:超時秒數,超時自動回滾isolation_READ_COMMITTED:隔離級別,預設通常為 READ_COMMITTED問題:所有方法統用 PROPAGATION_REQUIRED 導致查詢也開啟事務,產生不必要的資料庫鎖與連接持有。
優化:將查詢方法改為 PROPAGATION_NEVER 或 PROPAGATION_SUPPORTS,readOnly
<prop key="query*">PROPAGATION_NEVER</prop> <prop key="find*">PROPAGATION_SUPPORTS,readOnly</prop> <prop key="get*">PROPAGATION_SUPPORTS,readOnly</prop> <prop key="count*">PROPAGATION_NEVER</prop>
效果:查詢效率顯著提升,連接池佔用降低。
若
saveXxx()內部調用queryXxx(),而query*配置為PROPAGATION_NEVER,運行時會拋IllegalTransactionStateException(存在事務卻要求無事務)。
解決策略:
PROPAGATION_SUPPORTS,readOnly 替代 NEVER,兼容有/無事務上下文REQUIRES_NEW 獨立事務<bean id="baseTxProxy" abstract="true" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager" ref="transactionManager"/>
<property name="transactionAttributes">
<props>
<!-- 寫操作:必須事務,異常回滾 -->
<prop key="save*">PROPAGATION_REQUIRED,-Exception</prop>
<prop key="insert*">PROPAGATION_REQUIRED,-Exception</prop>
<prop key="update*">PROPAGATION_REQUIRED,-Exception</prop>
<prop key="delete*">PROPAGATION_REQUIRED,-Exception</prop>
<prop key="remove*">PROPAGATION_REQUIRED,-Exception</prop>
<!-- 讀操作:支持事務,只讀優化 -->
<prop key="get*">PROPAGATION_SUPPORTS,readOnly</prop>
<prop key="find*">PROPAGATION_SUPPORTS,readOnly</prop>
<prop key="query*">PROPAGATION_SUPPORTS,readOnly</prop>
<prop key="count*">PROPAGATION_SUPPORTS,readOnly</prop>
<prop key="list*">PROPAGATION_SUPPORTS,readOnly</prop>
<prop key="load*">PROPAGATION_SUPPORTS,readOnly</prop>
<!-- 特殊:批量導入獨立事務 -->
<prop key="batch*">PROPAGATION_REQUIRES_NEW,-Exception</prop>
<!-- 特殊:日誌記錄獨立提交 -->
<prop key="log*">PROPAGATION_REQUIRES_NEW</prop>
</props>
</property>
</bean>