본문 바로가기
Programming/Java

[JPA] Java EE 에서의 Transaction

by peter paak 2021. 3. 4.
728x90

Container managed 트랜잭션

Container-managed 트랜잭션

  • 자바 엔터프라이즈 빈에서는 기본적으로 container-managed 트랜잭션을 사용한다
  • 보통 메소드 시작시 트랜잭션 시작되고 메소드가 종료 직전에 commit된다
  • 각 메소드는 single 트랜잭션이 된다
  • Nested 혹은 멀티 트랜잭션은 메소드내에서 허용되지 않는다
  • Container-mananged 트랜잭션에서는 트랜잭션에 관련 메소드가 필요하지 않다
  • 그냥 필요한 빈 메소드가 트랜잭션 attribute를 붙혀주기만 하면된다 (@TransactionAttribute)
  • 만약 트랜잭션을 컨트롤 하고 싶다면 application-managed 트랜잭션을 사용해야 한다
  • Container-managed 트랜잭션을 사용하는 빈에서는 절대 트랜잭션 관리 메소드를 사용해서는 안된다.
java.sql.Connection의 commit, setAutoCommit, rollback 메소드
javax.jms.Session의 commit, rollback 메소드
javax.transaction.UserTransaction 인터페이스

Transaction Attributes

  • Transaction Attribute는 트랜잭션의 scope을 정의한다
  • scope은 매우 중요하다

  • 메소드 A에 트랜잭션이 걸려 있을 때 내부에 있는 메소드 B에는 트랜잭션이 걸릴 것인가 혹은 새로운 트랜잭션을 사용할 것인가 결정할 수 있어야 한다
  • 종류
    1. Required
    2. RequiresNew
    3. Mandatory
    4. NotSupported
    5. Supports
    6. Never

용어 정리

  • Client : 다른 빈, 위 그림에서는 Bean1이 되겠다

1. Required

  • Client가 트랜잭션을 시작하고 메소드를 실행한다면(T1), 메소드는 클라이언트 트랜잭션 내에서 실행된다. (T1)
  • Client가 트랜잭션을 시작하지 않으면(None) 컨테이너 시작전 매소드는 새로운 트랜잭션을 실행한다 (T2)
  • 모든 빈 메소드가 container-managed 트랜잭션에서 실행되도록 강제한다
  • 다른 트랜잭션을 override하지 않는 이상은 required는 사용하지 않는다

2. RequiresNew

  • 메소드가 항상 새로운 트랜잭션에서 호출하도록 할 때 사용
  • Client가 트랜잭션 안에서 시작되고 메소드를 실행한다면(T1), 컨테이너는 다음과 같은 단계를 밟는다
    1. client의 트랜잭션을 지연시킨다
    2. 새로운 트랜잭션을 실행한다 (T2)
    3. 호출을 메소드에 위임한다
    4. 메소드가 완료되면 client 트랜잭션을 실행한다
  • Client가 트랜잭션을 시작하지 않으면(None) 컨테이너 시작전 매소드는 새로운 트랜잭션을 시행한다 (T2)

3. Mandatory

  • Client가 트랜잭션 안에서 시작되고 메소드를 실행한다면(T1), 클라이언트 트랜잭션 내에서 실행된다(T1)
  • Client가 트랜잭션을 시작하지 않으면(None) TransactionRequiredException오류를 낸다 (Error)
  • 항상 Client 트랜잭션 안에서 실행하도록 강제할 때 사용

4. NotSupported

  • Client가 트랜잭션 안에서 시작되고 메소드를 실행한다면(T1), 메소드를 실행하기 전까지 클라이언트의 트랜잭션을 지연시킨다 (None)
  • 메소드가 완료되면 다시 클라이언트의 트랜잭션을 마저 시작한다
  • Client가 트랜잭션을 시작하지 않으면(None), 메소드가 실행되기 전까지 새로운 트랜잭션을 실행하지 않는다(None)
  • 트랜잭션이 필요하지 않을때 사용한다
  • 왜냐하면 트랜잭션은 항상 오버헤드를 유발하므로 성능향상에 도움이 된다

5. Supports

  • Client가 트랜잭션 안에서 시작되고 메소드를 실행한다면(T1), Client의 트랜잭션 내에서 메소드가 실행된다(T1)
  • Client가 트랜잭션을 시작하지 않으면(None), 메소드가 실행되기 전까지 새로운 트랜잭션을 실행하지 않는다(None)

6. Never

  • Client가 트랜잭션 안에서 시작되고 메소드를 실행한다면(None), RemoteException 오류를 낸다(Error)
  • Client가 트랜잭션을 시작하지 않으면(None), 메소드가 실행되기 전까지 새로운 트랜잭션을 실행하지 않는다(None)

요약

  • T1, T2는 컨테이너에 의한 트랜잭션
  • T1은 Client와 관련된 트랜잭션
    • 보통 Client는 다른 빈을 지칭한다
    • 내부에 메소드가 실행된다
  • T2 트랜잭션은 메소드가 실행되기 전에 컨테이너에 의해 실행된다
  • None은 컨테이너의 의해 실행되는 트랜잭션 내에서 메소드가 실행되지 않는다는 뜻

Transaction Attribute 세팅

  • 클래스나 메소드에 javax.ejb.TransactionAttribute어노테이션을 사용한다
  • javax.ejb.TransactionAttributeType 을 사용한다
    • NOT_SUPPORTED, REQUIRED....
  • 만약 클래스에 TransactionAttribute 를 사용하면 클래스 내부의 모든 메소드에 적용된다
  • 만약 메소드에 TransactionAttribute 를 사용하면 해당 메소드에만 적용된다
  • 둘다 적용되면 메소드는 Override한다
@TransactionAttribute(NOT_SUPPORTED)
@Stateful
public class TransactionBean implements Transaction {
...
    @TransactionAttribute(REQUIRES_NEW)
    public void firstMethod() {...}

    @TransactionAttribute(REQUIRED)
    public void secondMethod() {...}

    public void thirdMethod() {...}

    public void fourthMethod() {...}
}
  • firstMethod 실행시
    • 무조건 새로운 트랜잭션 생성
  • secondMethod 실행시
    • 현재 트랜잭션을 사용하거나, 트랜잭션없으면 새로운 트랜잭션 사용
  • thirdMethod 실행시
    • 무조건 트랜잭션을 실행하지 않는다
  • TransactionAttributeType

Rollback

  • Container-Managed 트랜잭션은 두가지 방법이 있다
    1. System Exception 오류가 발생할 경우 자동으로 rollback 실행
    2. EJBContext 인터페이스의 setRollbackOnly 메소드를 실행할 경우
  • 어플리케이션 오류가 난 경우는 자동으로 rollback하지 않으므로 명시적으로 rollback 해야한다

세션 빈의 인스턴스 변수 Syncronizing

  • SessionSynchronization 인터페이스는 트랜잭션 동기화 알림을 받기 위해 session 빈 인스턴스를 허용한다
    • 빈의 인스턴스 변수와 데이터베이스 값을 동기화 할 수 있다는 뜻이다
    • 컨테이너가 각 트랜잭션 스테이지에서 SessionSynchronization 메소드 (afterBegin, beforeCompletion, afterCompletion)를 실행한다
  1. afterBegin
    • 인스턴스에게 새로운 트랜잭션이 실행되었다고 알린다
    • 메소드 실행하기 직전에 컨테이너가 afterBegin을 실행한다
  2. beforeCompletion
    • 컨테이너는 beforeCompletion을 메소드 끝난 직후, 트랜잭션 commit 직전에 실행한다
    • beforeCompletion는 session 빈이 롤백하기 위한 마지막 기회이다 (setRollbackOnly를 호출)
  3. afterCompletion
    • 트랜잭션이 끝났다는 것을 알림
    • commit 되었다면 true, rollback되면 false 파라미터를 가진다

Container-Manged 트랜잭션을 허용하지 않는 메소드

  • 컨테이너가 지정한 트랜잭션 바운더리에 아래 메소드를 절대 사용하지 않는다
  • 왜냐면 해당 메소드들은 application-managed 트랜잭션이기 때문이다
java.sql.Connection의 commit, setAutoCommit, rollback 

javax.ejb.EJBContext의 getUserTransaction() 

javax.transaction.UserTransaction의 메소드들

정리

  • 트랜잭션은 scope이 매우 중요하다
  • scope은 빈의 메소드 내부에서 실행되는 다른 빈의 메소드에 현재 트랜잭션의 파생 여부를 결정
  • @TransactionAttribute에는 여러 scope이 존재한다
    1. Required
    2. RequiresNew
    3. Mandatory
    4. NotSupported
    5. Supports
    6. Never
728x90