복붙노트

[SPRING] 롤백 전용으로 표시된 트랜잭션 : 원인을 찾는 방법

SPRING

롤백 전용으로 표시된 트랜잭션 : 원인을 찾는 방법

내 @ 트랜잭션 방식 내에서 트랜잭션을 커밋하는 데 문제가 있습니다.

methodA() {
    methodB()
}

@Transactional
methodB() {
    ...
    em.persist();
    ...
    em.flush();
    log("OK");
}

method ()에서 method ()를 호출하면 메서드가 성공적으로 전달되고 내 로그에 "OK"가 표시됩니다. 그런데 나는

Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Transaction marked as rollbackOnly 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:521)
    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.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:622)
    at methodA()...

해결법

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

    1.메소드를 @Transactional로 표시하면 메서드 내에서 예외가 발생하면 주변 TX를 롤백으로 만 표시합니다 (사용자가 catch하더라도). @Transactional 주석의 다른 속성을 사용하여 롤백을 방지 할 수 있습니다.

    메소드를 @Transactional로 표시하면 메서드 내에서 예외가 발생하면 주변 TX를 롤백으로 만 표시합니다 (사용자가 catch하더라도). @Transactional 주석의 다른 속성을 사용하여 롤백을 방지 할 수 있습니다.

    @Transactional(rollbackFor=MyException.class, noRollbackFor=MyException2.class)
    
  2. ==============================

    2.나는 마침내 그 문제를 이해했다.

    나는 마침내 그 문제를 이해했다.

    methodA() {
        methodB()
    }
    
    @Transactional(noRollbackFor = Exception.class)
    methodB() {
        ...
        try {
            methodC()
        } catch (...) {...}
        log("OK");
    }
    
    @Transactional
    methodC() {
        throw new ...();
    }
    

    무슨 일이 일어나는가하는 것은 비록 methodB가 올바른 주석을 가지고있다하더라도 methodC는 그렇지 않다는 것이다. 예외가 발생하면 두 번째 @Transactional은 첫 ​​번째 트랜잭션을 롤백으로 만 표시합니다.

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

    3.다시 코딩하거나 다시 작성할 필요없이 일으키는 예외를 빠르게 가져 오려면 중단 점을 on으로 설정하십시오.

    다시 코딩하거나 다시 작성할 필요없이 일으키는 예외를 빠르게 가져 오려면 중단 점을 on으로 설정하십시오.

    org.hibernate.ejb.TransactionImpl.setRollbackOnly() // Hibernate < 4.3, or
    org.hibernate.jpa.internal.TransactionImpl() // as of Hibernate 4.3
    

    스택에서 올라가고, 보통은 어떤 인터셉터에게 올라간다. 거기에서 일부 catch 블록에서 발생한 예외를 읽을 수 있습니다.

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

    4.내 응용 프로그램을 실행하는 동안 나는이 예외로 고투했다.

    내 응용 프로그램을 실행하는 동안 나는이 예외로 고투했다.

    마지막으로 문제는 SQL 쿼리에있었습니다. 나는 쿼리가 잘못되었음을 의미합니다.

    귀하의 질의를 확인하십시오. 이것은 나의 제안이다.

  5. ==============================

    5.코드의 ... 섹션에 던져지고 잡히는 예외를 찾으십시오. 런타임 및 롤백 응용 프로그램 예외로 인해 다른 곳에서 잡히더라도 비즈니스 메서드에서 벗어날 때 롤백이 발생합니다.

    코드의 ... 섹션에 던져지고 잡히는 예외를 찾으십시오. 런타임 및 롤백 응용 프로그램 예외로 인해 다른 곳에서 잡히더라도 비즈니스 메서드에서 벗어날 때 롤백이 발생합니다.

    컨텍스트를 사용하여 트랜잭션이 롤백으로 표시되었는지 확인할 수 있습니다.

    @Resource
    private SessionContext context;
    
    context.getRollbackOnly();
    
  6. ==============================

    6.Bean.xml에서 transactionManager를 비활성화하십시오.

    Bean.xml에서 transactionManager를 비활성화하십시오.

    <tx:annotation-driven proxy-target-class="true" transaction-manager="transactionManager"/>
        <bean id="transactionManager"
            class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dataSource"></property>
        </bean>
    

    이 줄을 주석 처리하면 롤백을 일으키는 예외가 표시됩니다.

  7. ==============================

    7.솔루션에 대한 좋은 설명을 찾았습니다. https://vcfvct.wordpress.com/2016/12/15/spring-nested-transactional-rollback-only/

    솔루션에 대한 좋은 설명을 찾았습니다. https://vcfvct.wordpress.com/2016/12/15/spring-nested-transactional-rollback-only/

    1) 트랜잭션 제어가 실제로 필요하지 않은 경우 중첩 된 메소드에서 @Transacional을 제거하십시오. 따라서 예외가 있어도 트랜잭션이 영향을 미치지는 않습니다.

    또는:

    2) 중첩 된 메소드가 트랜잭션 제어를 필요로하는 경우 전파 정책에 대해 REQUIRE_NEW로 지정하십시오. 예외를 throw하고 롤백으로 만 표시 되더라도 호출자는 영향을받지 않습니다.

  8. from https://stackoverflow.com/questions/19302196/transaction-marked-as-rollback-only-how-do-i-find-the-cause by cc-by-sa and MIT license