[英]Avoid Transaction rollback in Spring
假设我有下面的代码:
@Autowired
private IManager1 manager1;
@Autowired
private IManager2 manager2;
@Autowired
private IManager3 manager3;
@Transactional
public void run() {
manager1.doStuff();
manager2.registerStuffDone();
manager3.doStuff();
manager2.registerStuffDone();
manager1.doMoreStuff();
manager2.registerStuffDone();
}
如果启动了任何异常,我想回滚“ doStuff()”方法完成的所有操作,但是我不想回滚“ registerStuffDone()”方法记录的数据。
我一直在阅读@Transactional注释的传播选项,但是我不知道如何正确使用它们。
每个经理在内部使用hiberante提交更改:
@Autowired
private IManager1Dao manager1Dao;
@Transactional
public void doStuff() {
manager1Dao.doStuff();
}
dao看起来像这样:
@PersistenceContext
protected EntityManager entityManager;
public void doStuff() {
MyObject whatever = doThings();
entityManager.merge(whatever);
}
这是我的applicationContext配置:
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSourcePool" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
</property>
</bean>
<bean id="entityManager" class="org.springframework.orm.jpa.support.SharedEntityManagerBean">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
想法?
您需要2个事务,一个事务要提交,另一个事务要回滚。
@Transactional(propagation = Propagation.REQUIRES_NEW, noRollbackFor={Exception1.class, Exception2.class})
public void registerStuffDone()() {
//code
}
然后,您的run方法将使用第一个事务并将其回滚,但是registerStuffDone方法将启动将要提交的第二个事务。
您正在使用声明式事务,并希望像程序意义那样进行控制。 因此,您需要更多实践和对Spring事务定义的深入理解,例如PROPAGATION,ISOLATION等。
程序化交易管理:这意味着您可以通过编程来管理交易。 这为您提供了极大的灵活性,但是很难维护。
VS
声明式事务管理:这意味着您将事务管理与业务代码分开。 您仅使用注释或基于XML的配置来管理事务。
也许,通过程序化事务管理来替代您的问题。
/** DataSourceTransactionManager */
@Autowired
private PlatformTransactionManager txManager;
public void run() {
try {
// Start a manual transaction.
TransactionStatus status = getTransactionStatus();
manager1.doStuff();
manager2.registerStuffDone();
manager3.doStuff();
manager2.registerStuffDone();
manager1.doMoreStuff();
manager2.registerStuffDone();
//your condition
txManager.commit(status);
//your condition
txManager.rollback(status);
} catch (YourException e) {
}
}
/**
* getTransactionStatus
*
* @return TransactionStatus
*/
private TransactionStatus getTransactionStatus() {
DefaultTransactionDefinition dtd = new DefaultTransactionDefinition();
dtd.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
dtd.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
dtd.setReadOnly(false);
return txManager.getTransaction(dtd);
}
注意:这并不意味着您需要始终使用一种方法,例如程序化事务管理。 我更喜欢混合方法。 对于简单的数据库服务,请使用声明式事务之类的简单方法,否则,只需在服务中使用程序化事务进行控制即可轻松保存逻辑。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.