@Transactional 어노테이션을 달면, 트랜잭션을 커밋하거나 예외가 발생하면 롤백하는 코드는 어떻게 동작하는가.
- 프록시 방식의 AOP가 적용된다.
- 트랜잭션을 처리하는 객체와 비즈니스 로직을 분리할 수 있다.
- @Transactional 어노테이션이 특정 클래스 안에 존재하면, 프록시 객체를 스프링 컨테이너에 등록한다. 실제 service layer 대신에 프록시를 스프링 빈으로 등록한다. 프록시 객체 내부에서 실제 service 객체를 참조한다.
프록시 객체는 service를 상속해서 만들어지기 때문에 다형성을 사용해서 프록시를 주입할 수 있다.
트랜잭션 어노테이션을 사용했는데 트랜잭션이 적용되지 않는 경우
public class HelloService {
public void hello() {
System.out.println("hello");
System.out.println(TransactionSynchronizationManager.isActualTransactionActive());
bye();
}
@Transactional(readOnly = true)
public void bye() {
System.out.println("bye");
System.out.println(TransactionSynchronizationManager.isActualTransactionActive());
}
}
// 실행 결과
hello
false
bye
false
HelloService의 hello()를 호출했을 때, bye() 코드에는 트랜잭션이 적용되어야 하는데, 트랜잭션이 적용되지 않는다.
그 이유는
1. 처음에 hello()를 호출할 때, @Transactional 어노테이션이 없어서 프록시 객체가 아닌 HelloService 객체에게 hello() 메서드 수행을 위임한다.
2. HelloService에서 hello()를 수행하고, bye()를 수행할 때 this.bye()를 호출하게 되므로, 프록시 객체를 통해서 메서드가 수행되지 않는다. 따라서 트랜잭션이 적용되지 않는다.
가장 간단한 해결법은 bye() 메서드를 다른 클래스로 분리하면 된다.
출처: 인프런 스프링 DB 2편 - 데이터 접근 활용 기술 강의
'Spring' 카테고리의 다른 글
Spring Boot 3 버전 주요 변경 사항 (0) | 2024.07.16 |
---|