본문 바로가기
IT/Java

@Transactional 사용시 주의 사항2 (내부호출 / AOP 내부호출)

by 성준하이 2023. 7. 11.
반응형

이전 포스팅에서 Transactional annotation에 대해서 다뤘었다.

자세한 내용은 아래 참고 포스팅을 참고 바란다.

 

해당 포스팅에서 언급했었고,

Spring AOP 기능에서 이슈가 있는 내부호출에 대한 내용을 다뤄볼 것이다.

 

먼저 아래 코드를 읽어보면,

public class TestTransactionAnnotationController {

    public void transactionalTest() {
        serviceA.insertValue();
        this.internal();
    }

    
@Transactional

    public void internal() {
        serviceA.insertValue();
        serviceA.insertValue();
        serviceA.insertValue();
        throw new ExceptionEx("errr");
    }
}

먼저 transactionalTest 를 읽어보면 serviceA에서 insertValue() 를 통해서 값을 넣고 동일 클래스 내에 internal을 호출한다.

그리고 그 메서드 내에서는 동일한 서비스인 insert를 3번 하고 에러가 터졌다.

 

transactional annotation 에 의해서 메서드에 Exception이 터지면 internal 은 rollback이 되서 결국 4번의 insert 중 1번의 insert 만 들어가야한다.

하지만 결과는 4번의 insert 가 모두 들어가있다.

이유는 transactional 은 aop 기능으로 동작을 하는데 클래스 단위로 동작을 하다보니 내부호출에서는 동작을 하지 않은 것이다.

 

해결하기 위해서 먼저 결론 코드를 보여주면 아래와 같다.

public class TestTransactionAnnotationController {

    @Autowired
    private TestTransactionAnnotationController cntr;

    public void transactionalTest() {
        serviceA.insertValue();
        cntr.internal();
    }

    
@Transactional

    public void internal() {
        serviceA.insertValue();
        serviceA.insertValue();
        serviceA.insertValue();
        throw new ExceptionEx("errr");
    }
}
이렇게 자기 자신을 주입 받아서 프록시 객체를 생성 후 해당 객체 내에서 internal 메서드를 호출하면 된다.

 


참고 포스팅

https://thenicesj.tistory.com/619

 

@Transactional annotation

spring에서 사용하는 annotation 중 하나인 이 Transactional annotation에 대해 소개하려고 한다. 사용은 메서드 상단에 설정을 해준다. 예제는 아래와 같다. @Transactional public void interal() { serviceA.transactionalTe

thenicesj.tistory.com

 

반응형

댓글