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의 프록시를 가지고 트랜잭션을 처리하는 방법을 더 알아봐야겠다.
반응형