Error - transaction error
| topics | 300-백엔드개발 305 데이터베이스 |
| types | 에러해결 |
| tags | #transaction #spring #database |
Transaction Error
트랜잭션 관련 에러는 대부분 전파(Propagation) 설정 문제거나 롤백 조건을 제대로 이해 못해서 생긴다.
상황
서비스 로직에서 @Transactional 붙였는데 롤백이 안 되거나, 반대로 롤백되면 안 되는데 롤백되는 경우.
자주 발생하는 문제들
1. Checked Exception은 롤백 안 됨
@Transactional
public void doSomething() throws IOException {
repository.save(entity);
throw new IOException("파일 에러"); // 롤백 안 됨!
}
Spring @Transactional은 기본적으로 RuntimeException만 롤백한다.
해결:
@Transactional(rollbackFor = Exception.class)
public void doSomething() throws IOException {
// 이제 모든 예외에서 롤백됨
}
2. 같은 클래스 내부 호출은 트랜잭션 안 탐
public void outer() {
inner(); // 트랜잭션 적용 안 됨!
}
@Transactional
public void inner() {
// ...
}
왜 이렇냐면: Spring AOP는 프록시 기반이라 외부에서 호출해야 프록시를 거친다. 내부 호출은 프록시를 우회함.
해결:
- 별도 클래스로 분리
self.inner()패턴 사용 (자기 자신 주입)
3. Propagation 설정 문제
@Transactional
public void parent() {
try {
child();
} catch (Exception e) {
// 예외 잡았으니 괜찮겠지?
}
}
@Transactional // 기본: REQUIRED
public void child() {
throw new RuntimeException(); // 전체 롤백됨!
}
REQUIRED는 부모 트랜잭션에 참여하기 때문에, child에서 예외 터지면 트랜잭션 자체가 rollback-only로 마킹된다.
해결:
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void child() {
// 별도 트랜잭션으로 분리
}
디버깅 팁
# <span id="applicationyml"></span>application.yml
logging:
level:
org.springframework.transaction: DEBUG
org.springframework.orm.jpa: DEBUG
트랜잭션 시작/커밋/롤백 로그 확인 가능.
결론
- Checked Exception 롤백하려면
rollbackFor명시 - 내부 호출은 트랜잭션 안 탄다
REQUIRES_NEW는 신중하게 (커넥션 2개 씀)