[英]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.