我必须更新两个数据源,作为一个事务的一部分。那就是 -
- 我在DB1中进行更新。
- 然后,我在DB2中进行了另一个更新。
如果DB2中的更新失败,我想回滚DB1和DB2以回滚。可以使用 @transactional来实现这一点吗?
这是示例代码 -
@Transactional(value="db01TransactionManager")
public void updateDb01() {
Entity01 entity01 = repository01.findOne(1234);
entity01.setName("Name");
repository01.save(entity01);
//Calling method to update DB02
updateDb02();
}
@Transactional(value="db02TransactionManager")
public void updateDb02() {
Entity02 entity02 = repository02.findOne(1234);
entity02.setName("Name");
repository02.save(entity02);
//Added this to force a roll back for testing
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}
我的问题是,UpdatedB02中的setrollbackonly((仅回落DB01事务。
我已经使用ChainedTranSactionManager -http://docs.spring.io/spring-data/commons/docs/docs/1.6.2.release/api/api/opi/org/springframework/数据/交易/链接TransactionManager.html
春季启动配置:
@Bean(name = "chainedTransactionManager")
public ChainedTransactionManager transactionManager(@Qualifier("primaryDs") PlatformTransactionManager ds1,
@Qualifier("secondaryDs") PlatformTransactionManager ds2) {
return new ChainedTransactionManager(ds1, ds2);
}
,然后您可以按以下方式使用它:
@Transactional(value="chainedTransactionManager")
public void updateDb01() {
Entity01 entity01 = repository01.findOne(1234);
entity01.setName("Name");
repository01.save(entity01);
//Calling method to update DB02
updateDb02();
}
public void updateDb02() {
Entity02 entity02 = repository02.findOne(1234);
entity02.setName("Name");
repository02.save(entity02);
//Added this to force a roll back for testing
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}
最好的方法是创建第三种方法,该方法将作为@Transactional
注释。
@Transactional(readOnly = false)
public void updateCommon(){
upbateDb01();
upbateDb02();
}
根据春季文档,当出现FIRTS注释时,事务控制开始,因此在这种情况下,当updateCommon
被调用时,单个事务将开始。更新但是,如果您使用CrudRepository
或类似的东西,这将起作用。
如果多个数据源,您可能会尝试使用全局交易管理概念。这是春季文档中的示例:
@Inject private PlatformTransactionManager txManager;
TransactionTemplate template = new TransactionTemplate(this.txManager);
template.execute( new TransactionCallback<Object>(){
public void doInTransaction(TransactionStatus status){
// work done here will be wrapped by a transaction and committed.
// the transaction will be rolled back if
// status.setRollbackOnly(true) is called or an exception is thrown
}
});
这是一个链接:http://spring.io/blog/2011/08/15/configuring-spring-and-and-jta-without-full-java-ee/我从来没有自己使用它,所以我没有深入探索这个话题。希望它会有所帮助
弄清楚了。
这些方法必须在不同的豆类中才能使用不同的事务管理器。
我相信您已经定义了下面的txn。
@Bean(name="db01TransactionManager")
@Autowired
DataSourceTransactionManager tm1(@Qualifier ("datasource1") DataSource datasource) {
DataSourceTransactionManager txm = new DataSourceTransactionManager(datasource);
return txm;
}
@Bean(name="db02TransactionManager")
@Autowired
DataSourceTransactionManager tm2(@Qualifier ("datasource2") DataSource datasource) {
DataSourceTransactionManager txm = new DataSourceTransactionManager(datasource);
return txm;
}
现在最简单的方法是尝试,捕获和回滚,以进行两项交易。但是,如果您仍然想委派,则有一个选择如下所示。
创建自己的和覆盖的回滚方法并使用它。
@Bean(name=“allTransactionManager")
@Autowired
DataSourceTransactionManager tm2(@Qualifier ("datasource1”) DataSource datasource1, @Qualifier ("datasource2") DataSource datasource2) {
DataSourceTransactionManager txm = new MyDataSourceTransactionManager(datasource1,datasouce2);
return txm;
}
并将您自己的TransactionManager定义为。
MyDataSourceTransactionManager extends DataSourceTransactionManager{
DataSourceTransactionManager tm1;
DataSourceTransactionManager tm2;
MyDataSourceTransactionManager(Datasource ds1,Datasource d2){
tm1 = new DataSourceTransactionManager(DataSource);
tm2 =new DataSourceTransactionManager(DataSource);
}
// override and for roll back, rollback for both of tm1 and tm2. Thus all actions are delegated in this class
}
然后,无论您想同步工作时,都将其用于DAO层。
@Transactional("allTransactionManager")
因此,现在我们拥有您自己的交易经理,这两种交易都可以滚动或合作。