簡體   English   中英

Spring Transaction沒有回滾

[英]Spring Transaction not rolling back

我有這樣的事情:

@Service
@Transactional
public class ServiceA {

    @Autowired
    SomeDAO1 dao1; 

    @Autowired
    ServiceB serviceB;

    public void methodServiceA() {

        serviceB.someMethodThatRunsInsertIntoDB(); 
        dao1.anotherMethodThatRunsInsertIntoDB(); 

    }

}

@Service
@Transactional
public class ServiceB {

     @Autowired
     Dao2 dao2;

     public void someMethodThatRunsInsertIntoDB() {
          dao2.insertXXX();
     }

}

我的問題是:如果serviceB.someMethodThatRunsInsertIntoDB()執行成功但dao1.anotherMethodThatRunsInsertIntoDB()拋出異常,則不會回滾serviceB所做的更改。 如果在dao1.anotherMethodThatRunsInsertIntoDB()發生異常,我需要回滾這些更改。 我怎樣才能做到這一點?

//已編輯

spring-servlet.xml中的事務配置

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory" />
    <property name="jpaDialect">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
    </property>
</bean>

如果一個dao使用EntityManager而另一個dao使用JdbcTemplate與DB交互是否相關?

// UPDATE - EntityManager配置

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
            <property name="showSql" value="true" />
            <property name="generateDdl" value="true" />
        </bean>
    </property>

你需要傳遞rollbackFor參數與您檢查的異常的類型。 看起來Spring默認只在未經檢查的異常上回滾。 更多細節: Spring事務:在Exception或Throwable上回滾

你需要在spring配置文件中使用<tx:annotation-driven/>來啟用注釋驅動的事務管理。

這是因為您的dao1.anotherMethodThatRunsInsertIntoDB()調用不支持當前事務(ServiceA事務)。

您需要在ServiceB類中使用低於傳播級別。

@Service
@Transactional(propagation = Propagation.REQUIRED)
public class ServiceB {

要求: Spring REQUIRED行為意味着如果當前bean方法執行上下文中已經打開的事務,將使用相同的事務。 如果不存在,則創建一個新的。 簡而言之,這意味着如果內部(第二個事務)方法導致事務回滾,則外部(第一個事務)方法將無法提交並且還將回滾事務。

傳播方式:通常,在事務范圍內執行的所有代碼都將在該事務中運行。 但是,您可以選擇在事務上下文已存在時執行事務方法時指定行為。 例如,代碼可以繼續在現有事務中運行(常見情況); 或者可以暫停現有交易並創建新交易。 Spring提供了EJB CMT中熟悉的所有事務傳播選項。 要閱讀有關Spring中事務傳播的語義,請參閱事務傳播

編輯
注意:默認情況下,將事務設置為回滾狀態的唯一例外是未經檢查的異常(如RuntimeException)。 如果您希望已檢查的異常也將事務設置為回滾,則必須將它們配置為執行此操作,例如。

@Service
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = YourCheckedException.class))
public class ServiceA {

注意:正如我所注意到的,聲明式事務管理是基於AOP的。 這意味着Spring將事務bean包裝到事務代理中,該代理負責啟動和提交事務。 這意味着必須由代理攔截方法調用才能成為事務性的。 您需要在Spring配置文件中確保以下配置。

<tx:annotation-driven transaction-manager="transactionManager" />

我的第一個建議是在方法級別使用@Transactional注釋,如果在類級別上真的不需要它。

第二件事,嘗試使用javax.transaction.Transactional注釋而不是org.springframework.transaction.annotation.Transactional ,Spring會自動處理傳播。

您還需要在使用@Transactional之前啟用事務管理,使用Spring Boot我們可以通過@EnableTransactionManagement標記Application類來@EnableTransactionManagement

但是,如果您願意,您也可以通過XML配置( <tx:annotation-driven /> )來完成此操作。 閱讀http://docs.spring.io/spring-data/jpa/docs/1.11.0.M1/reference/html/#transactions了解更多詳情

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM