2013-05-30 4 views
3

callable 인터페이스를 사용하여 serviceImpl에 멀티 스레딩 프로그램을 작성 중입니다. 스프링 트랜잭션 관리자를 사용하고 있습니다. DB에서 업데이트 작업을 실행하면 성공적으로 실행됩니다. 그러나 업데이트 된 데이터는 DB에 반영되지 않습니다. 하지만 멀티 쓰레딩없이 프로그램을 실행하면 데이터베이스에 업데이트됩니다.스프링 트랜잭션 관리자와 멀티 스레딩

이 내 구성

<tx:advice id="txAdvice" transaction-manager="txManager"> 
     <tx:attributes> 
      <tx:method name="*" /> 
      <tx:method name="find*" propagation="NOT_SUPPORTED" /> 
      <tx:method name="get*" propagation="NOT_SUPPORTED" /> 
     </tx:attributes> 
    </tx:advice> 
    <aop:config> 
     <aop:pointcut id="serviceOperation" expression="execution(* *..*ServiceImpl.*(..))" /> 
     <aop:advisor advice-ref="txAdvice" pointcut-ref="serviceOperation" /> 
    </aop:config> 
    <bean id="txManager" 
     class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 
     <property name="dataSource" ref="dataSource" /> 
    </bean> 

나는이 방법은 멀티 스레딩 지원 아닌지 확인하고 싶지 거래 manager.Just에 대한 또 다른 접근 방식으로 전환 할 수있다. 내 질문은 스프링 트랜잭션 관리자가 멀티 스레드를 지원합니까 (주석 또는 XML 선언을 의미하는 것입니까?) 업데이트 된 데이터가 필자의 경우 DB에 반영되지 않는 이유는 무엇입니까? 가장 좋은 대안은 무엇일까요?

답변

17

Spring에서 사용하는 트랜잭션 컨텍스트는 스레드 로컬 변수에 저장됩니다. 따라서 새로운 스레드를 시작하거나 호출 가능 코드를 사용하여 다른 스레드에서 코드를 실행하면이 코드는 Spring 트랜잭션 측면에서 시작된 트랜잭션의 일부가되지 않습니다. 이것이 귀하의 데이터가 데이터베이스에 나타나지 않는 이유입니다. 당신이 멀티 스레딩을 수행하는 방법을

+0

활성 트랜잭션을 두 번째 스레드로 전달할 수 있습니까? –

+0

나는 그것을 의심한다. 트랜잭션 측면에서 두 번째 스레드가 트랜잭션을 완료했는지 여부를 어떻게 알 수 있습니까? 스폰 된 스레드 (또는 호출 가능 객체)가 작업을 완료하기 전에 메소드가 리턴하면 누가 트랜잭션을 완결 할 것입니까? –

+0

그런 식으로하면 스레드의 적절한 동기화를 담당합니다. 예를 들어 스레드 A에서 작업을 시작하고 스레드 B에서 완료하는 것이 유용 할 수 있습니다 (따라서 스레드간에 트랜잭션 전달). –

3

당신의 천국의 쇼는, 그래서 난 단지 당신이 무엇을했는지 추측 할 수 있습니다 YourService.doSomething(), 그것은 createThreads에서

합니다. 각 스레드에 대해 DB 관련 작업을 수행하고 있습니다. 그게 맞습니까?

다른 대답에서 설명한 것처럼 트랜잭션 컨텍스트는 스레드 로컬 방식으로 저장됩니다. 따라서 스레드의 논리는 어떤 트랜잭션과도 관련이 없습니다. 당신이 이것을 확인할 수있는 한 가지는 doSomething()에서 쓰레드의 로직과 별개로 DB 액션을 수행한다는 것입니다. 스레드의 작업이 손실되는 동안 doSomething()에서 수행 한 db 작업이 커밋됨을 알 수 있습니다.

합리적으로 해결할 수있는 방법 중 하나는 일반적으로 작업 단위 역할을하는 응용 프로그램 서비스 계층을 사용하므로 서비스 경계와 비슷한 트랜잭션 경계가 있습니다. 스레드는 서비스에서 제공하는 작업을 호출해야합니다. 물론 그들은 모두 다른 거래가 될 것입니다.

이들 모두를 하나의 트랜잭션으로 원한다면 다른 방법은 개별 스레드가 DB 작업을 수행하는 대신 스레드가 이제는 무거운 작업을 수행하고 결과를 원래 스레드로 게시합니다 (예). 원래 스레드는 결과를 수집하고 DB 조치를 수행해야합니다.

개인적으로 나는 다른 스레드 주위에서 트랜잭션 컨텍스트를 수동으로 전달하지 않으려 고합니다. 이것은 단순히 선언적 트랜잭션이라는 전체 개념을 망치고있는 것입니다.

0

Spring에서 고유 한 TransactionSynchronizationManager를 구현하여 삽입하고자 할 수 있습니다. ThreadLocal 대신 InmheritableThreadLocal과 같은 것을 사용하십시오.