복붙노트

[SPRING] @Transactional의 이상한 동작 (propagation = Propagation.REQUIRES_NEW)

SPRING

@Transactional의 이상한 동작 (propagation = Propagation.REQUIRES_NEW)

여기 내 문제가있다 :

Java EE / Spring / Hibernate 애플리케이션에서 배치를 실행하고있다. 이 배치는 method1을 호출합니다. 이 메소드는 UserException (RuntimeException을 확장하는 클래스)을 던질 수있는 method2를 호출합니다. 다음과 같은 모습입니다.

@Transactional
public class BatchService implements IBatchService {
 @Transactional(propagation=Propagation.REQUIRES_NEW)
 public User method2(User user) {
   // Processing, which can throw a RuntimeException
 }

 public void method1() {
   // ...
   try {
     this.method2(user);
   } catch (UserException e) {
     // ...
   }
   // ...
 }
}

실행이 계속되면 예외가 catch되지만 method1이 끝날 때 트랜잭션이 닫히면 RollbackException이 throw됩니다.

다음은 스택 추적입니다.

org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Transaction marked as rollbackOnly
    at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:476)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:754)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:393)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:120)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at $Proxy128.method1(Unknown Source)
at batch.BatchController.method1(BatchController.java:202)

method2가이 예외를 throw하지 않으면 잘 동작합니다.

내가 시도한 것 :

그러나 그것은 아무 것도 바뀌지 않았습니다.

롤백이 발생한 다른 트랜잭션에서 예외가 발생하므로 왜 작동하지 않는지 이해할 수 없습니다. 이것 좀 봐 : Jpa transaction javax.persistence.RollbackException : 트랜잭션이 rollbackOnly로 표시되었지만 실제로 도움이되지 않았습니다.

누군가가 내게 단서를 줄 수 있다면 매우 감사 할 것입니다.

최신 정보

나는 propagation = Propagation.REQUIRES_NEW를 method2 (실제로 예외를 보내는 것)에 의해 호출 된 메소드에 설정함으로써 작동하게 만들었다. 이 메서드는 내 BatchService와 매우 비슷한 클래스에서 정의됩니다. 그래서 나는 그것이 method2가 아닌이 수준에서 작동하는 이유를 알지 못합니다.

비록 그것이 작동하고있다 할지라도, 이상한 행동을하기 때문에 문제는 여전히 열려 있습니다. 그리고 그것이 왜 그렇게 행동하지 않는지 이해하고 싶습니다.

해결법

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

    1.스프링 트랜잭션은 기본적으로 트랜잭션과 예외를 처리하는 프록시로 Spring 빈을 래핑하여 작동한다. method1 ()에서 method2 ()를 호출하면이 프록시를 완전히 무시하므로 새 트랜잭션을 시작할 수 없으며 효과적으로 call에 의해 열린 것과 동일한 트랜잭션에서 method2 ()를 호출하게됩니다. method1 ().

    스프링 트랜잭션은 기본적으로 트랜잭션과 예외를 처리하는 프록시로 Spring 빈을 래핑하여 작동한다. method1 ()에서 method2 ()를 호출하면이 프록시를 완전히 무시하므로 새 트랜잭션을 시작할 수 없으며 효과적으로 call에 의해 열린 것과 동일한 트랜잭션에서 method2 ()를 호출하게됩니다. method1 ().

    반대로, method1 ()에서 다른 주입 된 bean의 메소드를 호출하면 실제로 트랜잭션 프록시에서 메소드를 호출하게됩니다. 따라서이 외래 메소드가 REQUIRES_NEW로 표시되면 새 트랜잭션이 프록시에 의해 시작되고 method1 ()에서 예외를 catch하고 외부 트랜잭션을 재개 할 수 있습니다.

    이 내용은 설명서에 설명되어 있습니다.

  2. from https://stackoverflow.com/questions/15767914/strange-behaviour-with-transactionalpropagation-propagation-requires-new by cc-by-sa and MIT license