복붙노트

[SPRING] Spring @ 여러 데이터 소스 간의 트랜잭션과 트랜잭션

SPRING

Spring @ 여러 데이터 소스 간의 트랜잭션과 트랜잭션

하나의 트랜잭션의 일부로 두 개의 데이터 소스를 업데이트해야합니다. 그건 -

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 트랜잭션 만 롤백한다는 것입니다.

해결법

  1. ==============================

    1.ChainedTransactionManager를 사용하여이 문제를 해결했습니다. - http://docs.spring.io/spring-data/commons/docs/1.6.2.RELEASE/api/org/springframework/data/transaction/ChainedTransactionManager.html

    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();
    }
    
  2. ==============================

    2.가장 좋은 방법은 @Transactional로 주석 처리되는 세 번째 메서드를 만드는 것입니다.

    가장 좋은 방법은 @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-jta-without-full-java-ee/ 나는 그것을 스스로 사용하지 않았으므로이 주제를 깊이 탐구하지 않았다. 희망이 도움이 될 것입니다.

  3. ==============================

    3.그것을 알아 냈다.

    그것을 알아 냈다.

    메소드는 다른 트랜잭션 관리자를 사용할 수 있도록 다른 bean에 있어야합니다.

  4. ==============================

    4.나는 당신이 아래처럼 당신의 txns를 정의했다고 믿습니다.

    나는 당신이 아래처럼 당신의 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;
    }
    

    이제 가장 간단한 방법은 두 가지 트랜잭션 모두를 시도하고 catch하고 롤백하는 것입니다. 그러나 여전히 위임하기를 원할 경우 아래에 주어진 옵션이 있습니다.

    자신 만의 롤백 메서드를 만들고이를 사용하십시오.

    @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")
    

    이제는 두 가지 유형의 트랜잭션에 대해 롤백 또는 커밋 할 수있는 고유 한 트랜잭션 관리자가 있습니다.

  5. from https://stackoverflow.com/questions/48954763/spring-transactional-with-a-transaction-across-multiple-data-sources by cc-by-sa and MIT license