이번엔 내부 트랜잭션은 커밋되는데 외부 트랜잭션이 롤백되는 상황을 살펴보자.
참고로 결론부터 말하면 논리 트랜잭션이 하나라도 롤백되면 전체 물리트랜잭션은 롤백된다고 했다.
@Test
void outer_rollback(){
log.info("외부 트랜잭션 시작");
TransactionStatus outer = txManager.getTransaction(new DefaultTransactionAttribute());
//외부 트랜잭션인지 확인
log.info("outer.isNewTransaction()={}", outer.isNewTransaction());
log.info("내부 트랜잭션 시작");
TransactionStatus inner = txManager.getTransaction(new DefaultTransactionAttribute());
//내부 트랜잭션인지 확인
log.info("inner.isNewTransaction()={}", inner.isNewTransaction());
log.info("내부 트랜잭션 커밋");
txManager.commit(inner);
log.info("외부 트랜잭션 롤백");
txManager.rollback(outer);
}
실제로 코드를 돌려보면 전체 트랜잭션이 롤백되는걸 확인할 수 있다. 사실 내부 트랜잭션은 물리 트랜잭션에 관여할 수 없기 때문에 전체가 롤백되는걸 막을 수 없다.. 그래서 외부가 롤백되면 내부도 롤백된다.
그럼 이제 반대로 외부가 커밋인데 내부가 롤백될때는 어떤일들이 일어날까?
내부 트랜잭션은 물리트랜잭션과 관련이 없으므로 내부의 롤백이 아무런 영향을 주지 않을 것 같다. 하지만 전에 살펴본 원칙은 하나의 논리 트랜잭션이라도 롤백되면 물리 트랜잭션은 롤백된다는 것이었음. 어떤게 맞는걸까?
@Test
void inner_rollback(){
log.info("외부 트랜잭션 시작");
TransactionStatus outer = txManager.getTransaction(new DefaultTransactionAttribute());
//외부 트랜잭션인지 확인
log.info("outer.isNewTransaction()={}", outer.isNewTransaction());
log.info("내부 트랜잭션 시작");
TransactionStatus inner = txManager.getTransaction(new DefaultTransactionAttribute());
//내부 트랜잭션인지 확인
log.info("inner.isNewTransaction()={}", inner.isNewTransaction());
log.info("내부 트랜잭션 롤백");
txManager.rollback(inner);
log.info("외부 트랜잭션 커밋");
txManager.commit(outer);
}
테스트를 실행해보면 기존 테스트들과는 달리 예외가 발생하며 테스트가 실패한다.