2016-06-23 1 views
0

두 가지 다른 데이터 소스가 사용되는 시나리오가 있습니다.datasoure-2 트랜잭션을 사용하는 다른 서비스에서 호출 할 때 자체 데이터 소스 트랜잭션에서 메소드 실행

코드는 아래와 같습니다 (트랜잭션을 사용하지만 datasource2 함께) 데이터 소스 2 서비스 클래스 메소드를 호출 (트랜잭션이 사용 가능)

데이터 소스 (1) 서비스 클래스. 내 요구 사항은이 계층 구조에서 호출 할 때 별도의 트랜잭션으로 persistOneByOne()을 실행하는 방법입니다. 예외가 발생하면 해당 레코드는 지속되지만 for 루프는 in이 다른 레코드를 처리하기 때문에 진행됩니다. 이 동작을 어떻게 수행합니까?

는 // 서비스 클래스 2는 사용하는 데이터 소스-1 개의 트랜잭션 (transaction)을 사용 AOP 서비스 클래스 2는 AOP

으로 사용 가능 거래입니다 데이터 소스-2라는 서로 다른 데이터 소스를 사용하여 //

public class DataSource1ServiceClass1{ 
    DataSource2OtherServiceClass service2; 

    public void processData(){ 
      service2.prepareAndPeristData(); 
     } 
    } 

public class DataSource2OtherServiceClass{ 

    public void prepareAndPeristData(){ 
     try{ 
      for(int i=0;i<10;i++) 
       { 
      // pre processing before persisting a single record 
      persistOneByOne(); 
       } 
      }catch (Exception e){ 
       log.error("Error occurred.. so didn't persist record as expected"}; 
      } 


    public void persistOneByOne() 
     { 
      dao.persist(); 
     } 
} 

구성 XML 파일 : 나는 PERSIS를 달성하려면 어떻게

<bean id="txManager" 
     class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 
     <property name="dataSource" ref="dataSource" /> 
    </bean> 

    <tx:advice id="txAdvice" transaction-manager="txManager"> 
     <tx:attributes> 
      <tx:method name="*" /> 
     </tx:attributes> 
    </tx:advice> 

    <aop:config> 
     <aop:pointcut id="allServices" 
      expression="execution(* .service.impl.*.*(..))" /> 
     <aop:advisor advice-ref="txAdvice" pointcut-ref="allServices" /> 
    </aop:config> 


<bean id="txManager2" 
     class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 
     <property name="dataSource" ref="otherDataSource" /> 
    </bean> 

    <tx:advice id="txAdvice2" transaction-manager="txManager2"> 
     <tx:attributes> 
      <tx:method name="*" /> 
     </tx:attributes> 
    </tx:advice> 

    <aop:config> 
     <aop:pointcut id="allOtherServices" 
      expression="execution(* .service2.impl.*.*(..))" /> 
     <aop:advisor advice-ref="txAdvice2" pointcut-ref="allOtherServices" /> 
    </aop:config> 

tOneByOne()은 자체 트랜잭션에서 실행됩니다. 예외가 발생하면 해당 단일 행을 롤백합니다.

답변

0

시나리오가 저장 점 기반 데이터베이스 상호 작용에 맞다고 생각합니다. Spring은 전파를 NESTED으로 지원한다.

코드의 persistOneByOne() 메서드에 중첩 전파 조언을 적용하는 경우, 메소드가 실행될 때마다 세이브 포인트를 생성하고, 이벤트가 발생하면 마지막 세이브 포인트로 롤백합니다. 그런 다음 계속하십시오.

기술적으로 전파 지침을 적용하여 수행 할 수도 있지만 호출 할 때마다 새 트랜잭션이 열립니다. 대량 거래.

당신은 자세한 내용은이 볼 수 있습니다 : http://www.marcobehler.com/make-it-so-java-db-connections-and-transactions-html/spring-transactional-propagation-propagation-nested.html

또한, 당신의 transactionManager와 대신 @Transactional 주석 방법/클래스에 주석을 다음 txManager2에 대한 귀하의 congiuration에서 트랜잭션 조언을 제거 할 수 있습니다. 문서 : http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/transaction/annotation/Transactional.html

당신은 당신의 구성이를 추가해야합니다

public class DataSource2OtherServiceClass{ 

    @Transactional(rollbackFor = {Exception.class}, propagation=PROPAGATION.REQUIRES_NEW, transactionManager="txManager2") 
    public void prepareAndPeristData(){ 
     try{ 
      for(int i=0;i<10;i++) 
       { 
      // pre processing before persisting a single record 
      persistOneByOne(); 
       } 
      }catch (Exception e){ 
       log.error("Error occurred.. so didn't persist record as expected"}; 
      } 

    @Transactional(rollbackFor = {Exception.class}, propagation=PROPAGATION.NESTED, transactionManager="txManager2") 
    public void persistOneByOne() 
     { 
      dao.persist(); 
     } 
} 
: 당신이 클래스는 다음과 같이 보일 것이와

<tx:annotation-driven proxy-target-class="true"/>