首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Spring 事務管理配置最佳實踐:Service 層統一控制

     編輯:Java 相關知識

為什麼事務要在 Service 層?

一個業務操作往往涉及多個 DAO 調用(如:扣款 + 記錄流水 + 發送通知)。若事務在 DAO 層,每個 DAO 獨立提交/回滾,無法保證業務原子性。Service 層作為業務邊界,統一開啟/提交/回滾事務,才能保證多表操作一致性。

事務配置三要素(回顧)

  1. DataSource / SessionFactory
  2. PlatformTransactionManager
  3. 代理機制(五種方式,現代專案首選 @Transactional)

五種配置方式速覽(同 126903,此處精簡)

方式一:TransactionProxyFactoryBean 獨立代理

每個 Bean 一個代理定義,配置冗餘,不推薦新專案使用。

方式二:父 Bean 共享屬性

abstract="true" 定義基類,子 Bean 繼承 parent="txBase"。減少重複但仍需逐個聲明。

方式三:BeanNameAutoProxyCreator + TransactionInterceptor

<bean id="txInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">
    <property name="transactionManager" ref="txManager"/>
    <property name="transactionAttributes">
        <props><prop key="*">PROPAGATION_REQUIRED</prop></props>
    </property>
</bean>
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
    <property name="beanNames"><list><value>*Service</value></list></property>
    <property name="interceptorNames"><list><value>txInterceptor</value></list></property>
</bean>

通配符批量代理 Service 層,無需修改業務代碼。

方式四:tx/aop 命名空間(XML 專案推薦)

<tx:advice id="txAdvice" transaction-manager="txManager">
    <tx:attributes>
        <tx:method name="save*" propagation="REQUIRED" rollback-for="Exception"/>
        <tx:method name="update*" propagation="REQUIRED" rollback-for="Exception"/>
        <tx:method name="delete*" propagation="REQUIRED" rollback-for="Exception"/>
        <tx:method name="get*" propagation="SUPPORTS" read-only="true"/>
        <tx:method name="find*" propagation="SUPPORTS" read-only="true"/>
        <tx:method name="*" propagation="REQUIRED"/>
    </tx:attributes>
</tx:advice>
<aop:config>
    <aop:pointcut id="serviceMethods" expression="execution(* com.service..*Service.*(..))"/>
    <aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethods"/>
</aop:config>

方式五:全注解(現代標準)

<tx:annotation-driven transaction-manager="txManager"/>
<context:component-scan base-package="com.service"/>
@Service
@Transactional(rollbackFor = Exception.class) // 默認 REQUIRED
public class OrderService {
    @Autowired OrderDao orderDao;
    @Autowired AccountDao accountDao;

    @Transactional(readOnly = true)
    public Order getOrder(Long id) { return orderDao.findById(id); }

    public void createOrder(Order order) {
        accountDao.deduct(order.getUserId(), order.getAmount()); // DAO 1
        orderDao.save(order);                                     // DAO 2
        // 任一異常,整體回滾
    }
}

關鍵配置細節

傳播行為選擇

  • REQUIRED (默認):業務主流程,確保同一事務
  • REQUIRES_NEW:日誌、審計、獨立提交
  • SUPPORTS + readOnly=true:查詢方法,無事務開銷
  • NESTED:保存點回滾(需 JDBC 支援)

rollbackFor 陷阱

默認僅回滾 RuntimeException 和 Error。業務異常 (Checked Exception) 必須顯式聲明:

@Transactional(rollbackFor = {BizException.class, Exception.class})
public void transfer(...) throws BizException { ... }

只讀優化

@Transactional(readOnly = true)
public List listOrders() { ... }
  • Hibernate:跳過髒檢查、不生成 UPDATE
  • 數據庫:可能使用只讀副本、優化鎖
  • 連接池:可配置只讀連接

常見錯誤與避坑

  1. 同類內部調用失效:this.method() 繞過代理。
    解決:注入自身 @Autowired SelfService self 或拆分類。
  2. 異常被捕獲吞噬:try-catch 未重拋,事務不回滾。
    解決:throw new RuntimeException(e) 或 TransactionAspectSupport.currentTransactionStatus().setRollbackOnly()。
  3. 非 public 方法不生效:Spring AOP 默認僅代理 public 方法。
    解決:改 public 或使用 AspectJ 編譯時織入。
  4. 數據源未綁定事務管理器:多數據源時需指定 @Transactional("txManager2")。

事務配置核心原則:Service 層統一、默認 REQUIRED、查詢 SUPPORTS+readOnly、業務異常顯式 rollbackFor、避免同類內部調用。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved