1つのトランザクションの一部として2つのデータソースを更新する必要があります。あれは -
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/1.6.2.RELEASE/api/org/springframework/data/transaction/ChainedTransactionManager.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
として注釈が付けられる3番目のメソッドを作成することです。
@Transactional(readOnly = false)
public void updateCommon(){
upbateDb01();
upbateDb02();
}
春のドキュメントによると、トランザクションコントロールは最初のアノテーションが表示されたときに開始されるため、この場合、updateCommon
が呼び出されたときに単一のトランザクションが開始されます。 [〜#〜] update [〜#〜]しかし、これは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-jta-without-full-Java-ee/ 使用したことがありません私自身のため、このトピックを深く探求しませんでした。それが役に立てば幸い
私はあなたがあなたのtxnsを以下のように定義したと信じています。
@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;
}
そして、独自のトランザクションマネージャーを次のように定義します。
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")
これで、両方のタイプのトランザクションに対してロールバックまたはコミットできる独自のトランザクションマネージャができました。
理解した。
異なるトランザクションマネージャを使用できるようにするには、メソッドを異なるBeanにする必要があります。