복붙노트

[SPRING] 하위 메서드에서 예외가 발생할 때 트랜잭션에 대해서만 롤백 없음

SPRING

하위 메서드에서 예외가 발생할 때 트랜잭션에 대해서만 롤백 없음

내 응용 프로그램에서 트랜잭션을 처리하기 위해 Hibernate + spring + @Transactional 어노테이션을 사용하고있다.

트랜잭션 관리자는 다음과 같이 선언됩니다.

<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory"/>
</bean>

<tx:annotation-driven transaction-manager="transactionManager"/>

이것은 대부분의 경우에 잘 작동하지만 두 가지 메소드가 모두있는 문제를 발견했습니다. @Transactional :

package temp;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

public class OuterTestService {
    @Autowired
    private InnerTestService innerTestService;

    @Transactional
    public void outerMethod() {
        try {
            innerTestService.innerTestMethod();
        } catch (RuntimeException e) {
            // some code here
        }
    }
}

package temp;

import org.springframework.transaction.annotation.Transactional;

public class InnerTestService {

    @Transactional
    public void innerTestMethod() throws RuntimeException {
        throw new RuntimeException();
    }
}

OuterTestService # outerMethod ()를 호출하면 예외가 발생합니다.

org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only

하나의 트랜잭션 (중첩 트랜잭션 없음)이 있기 때문에 전체 outerTestMethod () 트랜잭션은 롤백 전용으로 표시됩니다.

나는 이것을 noRollbackFor를 사용하여 쉽게 극복 할 수 있음을 발견했다.

package cz.csas.pdb.be.service.tempdelete;

import org.springframework.transaction.annotation.Transactional;

public class InnerTestService {

    @Transactional(noRollbackFor = RuntimeException.class)
    public void innerTestMethod() throws RuntimeException {
        throw new RuntimeException();
    }
}

그러나 이것은 모든 방법에 명시 적으로 사용되어야합니다. 이 오류는 롤백되는 테스트 중에 발생하지 않으므로 허용되지 않습니다.

내 질문 - 트랜잭션을 시작한 메서드 (이 경우 outerTestMethod ())에서 예외가 발생할 때만 트랜잭션이 롤백되도록 자동으로 설정하는 방법이 있습니까?

해결법

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

    1.다른 주석을 만듭니다 (예 : @ NoRollbackTransactional, 다음과 같은 것 :

    다른 주석을 만듭니다 (예 : @ NoRollbackTransactional, 다음과 같은 것 :

    @Transactional(noRollbackFor = RuntimeException.class)
    public @interface NoRollbackTransactional {
    }
    

    그리고 당신의 방법에 이것을 사용하십시오. 반면 Donal의 의견에 동의하는 경우 트랜잭션 범위를 수정해야합니다. 즉, @Transactional을 다른 @Transactional에서 호출하는 것이 일반적으로 좋지 않습니다.

  2. ==============================

    2.globalRollbackOnParticipationFailure를 해제해야 할 수도 있습니다.

    globalRollbackOnParticipationFailure를 해제해야 할 수도 있습니다.

    주변 거래 내에서 독립적 인 거래가 있었을 때이 문제가있었습니다. 독립 트랜잭션이 실패하면 주변 트랜잭션에도 실패합니다.

    참가 깃발을 끄는 것은 나를 위해 이것을 해결했다 :

    <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="globalRollbackOnParticipationFailure" value="false" />
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>
    
  3. from https://stackoverflow.com/questions/6097012/no-rollback-only-for-transaction-when-exception-occurs-in-submethod by cc-by-sa and MIT license