논리적 트랜잭션은 각 메서드마다 할당됩니다. 각 논리적 트랜잭션은 rollback-only 상태를 각각 결정할 수 있습니다. 즉. 외부 트랜잭션과 내부 트랜잭션은 논리적으로 별개입니다.
물론 REQUIRED일때 모든 논리적 트랜잭션은 하나의 물리적 트랜잭션에서 동작합니다.
따라서 내부 트랜잭션의 rollback-only 표시는 외부 트랜잭션이 commit하려 할때 영향을 미칩니다.(내부 트랜잭션에서 rollback이 일어나면 외부 트랜잭션에서도 rollback이 일어날 수 있다는 뜻인듯?)
하지만, 내부 트랜잭션에 rollback-only 표시가 되어있고, 외부 트랜잭션은 rollback할 계획이 없는 경우에 rollback되는 상황은 기대하지 않은 상황입니다. 이런 상황일때 UnexpectedRollbackException
이 발생합니다. 예외가 발생하는 것은 예상할 수 있는 상황이기 때문에 caller(외부 트랜잭션을 호출한 얘)는 rollback이 일어났을때 commit이 일어났다고 오해하는 일은 없습니다. 따라서 내부 트랜잭션이 rollback-only 표시를 했다면 이를 모르는 외부 호출자가 commit을 호출할 수 있기 때문에 외부 호출자는 UnexpectedRollbackException
을 받아 rollback이 일어났다는 것을 알 수 있어야 합니다.
REQUIRED에서 내부 트랜잭션이 rollback되면 외부 트랜잭션도 rollback된다. 외부 트랜잭션을 호출한 caller는 UnexpectedRollbackException
을 통해 rollback이 발생됐음을 안다.
REQUIRED_NEW인 경우 논리적 트랜잭션은 완벽하게 서로 다른 물리적 트랜잭션이다. 물리적 트랜잭션이 다르기 때문에 commit과 rollback은 독립적으로 이루어진다. 따라서 외부 트랜잭션은 내부 트랜잭션에 영향을 받지 않는다.
NESTED는 rollback이 가능한 여러개의 save point가 있는 하나의 물리적 트랜잭션이다. 이런 부분적 Rollback은 내부 트랜잭션이 자기만의 범위를 가지고 rollback을 할 수 있도록 한다. 따라서 외부 트랜잭션은 몇몇 operation이 rollback되었어도 계속해서 진행될 수 있다. 이런 설정은 JDBC savepoint를 이용하는데 그래서 JDBC resource transaction과만 함께 쓰일 수 있다.
내부트랜잭션(REQUIRED)에서 예외를 throw -> 외부에서 try-catch로 잡고 아무것도 안함
모두 rollback된다
내부 트랜잭션에서 예외가 발생 -> 내부트랜잭션에서 try-catch로 무시
모두 commit 된다.