Spring/JPA

태태개발일지 - 트랜잭션?

태태코 2024. 12. 3. 11:24
반응형

트랜잭션

 

jpa를 공부하다 보니

"한  클래스안에서 @trancational이 걸려있는 메서드를  @trancational이 걸려있는 메서드 내에서 사용하면 트랜잭션 적용이 안된다" 라는 사실을 알 게 되었다.

 

그이유는 다음과 같다.

 

Spring에서 트랜잭션은 기본적으로 AOP를 사용해 구현됩니다.

이 AOP는 프록시 객체를 생성하여 트랜잭션 관리를 처리합니다. 하지만 클래스 내에서 자기 자신(this)의 메서드를 호출하면 프록시가 아닌 실제 객체의 메서드를 호출하기 때문에 트랜잭션이 적용되지 않을 수 있습니다.

 

@Service
public class MyService {
    
    @Transactional
    public void methodA() {
        // 트랜잭션 시작
        System.out.println("methodA: 트랜잭션 시작");

        methodB(); // 내부 호출 (트랜잭션 적용 X)
    }

    @Transactional
    public void methodB() {
        // 트랜잭션 적용되지 않음
        System.out.println("methodB: 트랜잭션이 적용되지 않음");
    }
}

 

이렇게 되면 메서드 B는 트랜잭션이 적용이 안된 다는 것이다.

 

 

해결방법

 

1. 메서드 분리 (외부 호출로 처리)

@Service
public class MyServiceA {
    @Autowired
    private MyServiceB myServiceB;

    @Transactional
    public void methodA() {
        System.out.println("methodA: 트랜잭션 시작");

        myServiceB.methodB(); // 외부 호출로 트랜잭션 적용
    }
}
@Service
public class MyServiceB {
    @Transactional
    public void methodB() {
        System.out.println("methodB: 트랜잭션 적용");
    }
}

 

아래와같이 Service로 다른 클래스로 만들어서 외부호출을 통해서 트랜잭션을 적용하는 방법이있고,

 

2. Proxy 객체 사용 강제

트랜잭션 메서드 호출 시 프록시 객체를 사용하도록 강제합니다. ApplicationContext를 이용하면 내부 호출 문제를 해결할 수 있습니다.

@Service
public class MyService {
    @Autowired
    private ApplicationContext context;

    @Transactional
    public void methodA() {
        System.out.println("methodA: 트랜잭션 시작");

        // Proxy 객체를 통해 methodB 호출
        context.getBean(MyService.class).methodB();
    }

    @Transactional
    public void methodB() {
        System.out.println("methodB: 트랜잭션 적용");
    }
}

 

프록시 객체를 호출하여 사용하는 방법이있다.

 

우선 AOP의 프록시를 가지고 트랜잭션을 처리하는 방법을 더 알아봐야겠다.

 

 

반응형