← 질문 목록
#16깊이 0
@Transactional이 걸리지 않는 경우는?
프록시를 거치지 않고 메서드에 들어갔을 때다. 스프링의 트랜잭션은 코드가 아니라 프록시가 여는 것이다. 프록시를 통과하지 않으면 애초에 열릴 기회가 없다.
가장 흔한 자리가 자기 호출이다. 같은 클래스 안에서 this.method()로 부르면 그 호출은 프록시를 지나지 않고 실제 객체로 곧장 들어간다. 애너테이션은 붙어 있는데 아무 일도 일어나지 않는다. 로그도 예외도 없어서 원인을 찾기 어렵다.
- 1. 다른 빈에서 프록시로: 빈 참조로 부른다. **여기서 트랜잭션이 열린다**
- 2. 프록시에서 실제 객체로: 메서드 실행
- 3. 실제 객체에서 실제 객체로: this.method(). 프록시를 건너뛴다 — 안 걸린다
private 메서드도 같은 이유로 안 걸린다. CGLIB 프록시는 상속으로 만들어지는데 private은 재정의할 수 없다. final 메서드와 final 클래스도 마찬가지다.
주의
걸렸는데 안 되돌아가는 경우도 있다. 기본 롤백 대상은 unchecked 예외라, 체크 예외를 던지면 트랜잭션은 그대로 커밋된다. 되돌리려면 rollbackFor를 명시해야 한다.
자기 호출은 프록시를 거치지 않으므로 부가기능이 빠진다. 우회책을 아는 것보다 구조를 아는 쪽이 중요하다. 우회책은 대개 그 메서드를 다른 빈으로 꺼내는 것이고, 꺼내야 한다는 판단 자체가 구조 이해에서 나온다.
추천 꼬리질문
관련 질문
- 스프링 AOP의 프록시 자기 호출 시 무엇이 문제인가?프레임워크자기 호출은 @Transactional이 조용히 안 걸리는 대표 원인이다.
- 내부 메서드 호출에 부가기능이 빠지는 이유는?프레임워크@Transactional은 AOP 프록시 방식으로 동작하며, 내부 메서드 호출 시 프록시를 거치지 않아 트랜잭션이 적용되지 않는 현상이 부가기능 누락과 동일한 원리다.
- 외부 롤백과 무관한 기록은 어떻게 남기는가?프레임워크외부 롤백과 무관한 기록을 남기기 위해서는 @Transactional의 적용 범위와 전파 속성을 이해해야 한다.
- 자동 구성은 어떤 조건에서 물러나는가?프레임워크스프링의 마법이 조건이 어긋나면 소리 없이 물러난다는 같은 함정을 다룬다.
- 부모 트랜잭션과 무관하게 동작하려면 어떤 전파 속성을 쓰는가?프레임워크