9.5.1. Understanding the Spring Framework’s declarative transaction implementation

트랜잭션 관리 대상이 되는 클래스에 @Transactional 어노테이션을 붙이고 설정 파일에는 <tx:annotation-driven/>요렇게 추가하면 됩니다.

사용자 삽입 이미지그렇게 하면 내부에서는 AOP를 사용하여 타겟에 대한 호출은 (1)AOP 프록시를 호출하게 되고 그 다음 (2)트랜잭션을 만들고 (3)트랜잭션 내에서 원하는 작업을 하고 (4)실제 작업을 한 뒤에 다시 (3)또 해당 작업이 끝난 뒤 원하는 작업을 하고 (2)해당 트랜잭션을 커밋 하거나 롤백하고 (5)최종 결과를 호출한 녀석에게 돌려 줍니다.

9.5. Declarative transaction management

Spring도 EJB의 CMT 처럼 선언적인 트랜잭션을 제공하지만 몇 가지 차이가 있습니다.

  • Spring은 EJB의 CMT 처럼 JTA에 종속되어 있지 않습니다. 설정 내용을 살짝 바꾸기만 하면 JDBC, Hibernate, JDO 등을 자유롭게 사용할 수 있습니다.
  • EJB(bean) 만 트랜잭션을 처리할 수 있었는데 반해 Spring은 일반 클래스에도 적용할 수 있습니다.
  • 선언적으로 롤백 룰을 설정할 수 있습니다.
  • AOP를 사용하여 트랜잭션 처리를 할 때 사용자가 원하는 부가적인 기능을 실행할 수 있습니다. EJB에서는 할 수 없습니다.
  • The Spring Framework does not support propagation of transaction contexts
    across remote calls, as do high-end application servers

롤백 룰을 사용하여 특정 예외가 발생했을 때에만 롤백이 되도록 선언적으로 지정할 수 있습니다.

EJB의 경우 기본 설정이 RemoteException를 제외한 checked 예외(application exception)가 발생하면 롤백하지 않고 Runtime exception(system exception)이 발생하면 자동으로 롤백하도록 되어 있습니다.

이런 기본 설정이 유용하기 때문에 Spring도 EJB의 기본 설정을 따라서 unchecked exception 가 발생할 때에만 자동으로 롤백하도록 기본 설정되어 있습니다.

9.5.1. Understanding the Spring Framework’s declarative transaction implementation

Spring의 선언적인 트랜잭션 관리라는 신비를 파해칩니다.

9.5.2. A first example

예제 ㄱㄱ..

9.5.3. Rolling back

간단한 설정을 통해서 롤백을 제어 하는 방법을 설명합니다.

9.5.4. Configuring different transactional semantics for different beans

여러 bean들에 각각 다른 트랜잭션을 적용하는 방법을 설명합니다.

9.5.5. <tx:advice/> settings

<tx:advice/> 태그를 사용하여 트랜잭션 속성을 설정합니다.

9.5.6. Using @Transactional

@Transactional 어노테이션을 사용하여 XML 설정 대신 트랜잭션 대상이 될 bean을 지정할 수 있습니다.

9.5.7. Advising transactional operations

트랜잭션 처리를 해야하는 advice를 엮는 방법을 설명합니다.

9.5.8. Using @Transactional with AspectJ

Spring Container에서 관리하는 bean 말고도 AspectJ를 사용하여 @Trancsational 어노테이션을 적용할 수 있습니다.

9.4. Resource synchronization with transactions

이번에 볼 것은 이전 글에서 살펴보았던 (1)각 종 TransactionManager를 사용하여 어떻게 Hibernate나 JDBC에 있는 트랙잭션 관련 API를 사용하느냐 (2)해당 자원[footnote]Hibernate나 JDBC, JTA등의 실제 트랜잭션을 처리하는 녀석들을 Resource라고 표현하고 있습니다.[/footnote]을 잘 가져왔고 creation/reuse/cleanup/trigger/transaction
synchronization이 필요할 때 잘 동작하는지 확인 하는 것 입니다.

9.4.1. High-level approach

추천하는 방법으로 추상화 단계가 높은 Template 클래스를 사용하여  creation/reuse/cleanup/trigger/transaction
synchronization 이런 일들을 할 수 있습니다.

예외를 전부 매핑해줍니다.

내부적으로 해당 자원의 API를 사용하는 것이지 Spring 의 API가 대체하는 것은 아닙니다.
‘수’ 작업으로 만든 HibernateTemplate

ex) HibernateTemplate, JdbcTemplate, JdoTemplate

9.4.2. Low-level approach

추상화 단계가 낮은 Utils 클래드를 사용해서 원하는 작업을 할 수도 있습니다.

Connection conn = DataSourceUtils.getConnection(dataSource);
이런식으로 사용하며 역시 예외를 전부 맵핑해서 좀더 유용한  unchecked 예외로 뿌려 줍니다.

ex) DataSourceUtils, SessionFactoryUtils, PersistenceManagerFactoryUtils

9.4.3. TransactionAwareDataSourceProxy

가장 낮은 단계의 클래스로 타겟 DataSource의 프록시입니다. Spring이 관리하는 트랙잭션이라는 정보를 추가하기 위해 타겟 DataSource를 감쌉니다. DataSource 인터페이 타입을 요구하는 기존 코드에서 작업해야 한다면 이 걸 사용할 수 있겠습니다.

그런 경우가 아니라면 추상화 단계가 높은 것을 사용하길 권장합니다.

9.3. Key abstractions

Spring의 트랜잭션 추상화 계층에서 트랜잭션 전략(transaction strategy)이 중요한 개념 중 하나입니다.

트랜잭션 전략을 위해서 PlatformTransactionManager 인터페이스를 사용합니다.

public interface PlatformTransactionManager {

    TransactionStatus getTransaction(TransactionDefinition definition)
        throws TransactionException;

    void commit(TransactionStatus status) throws TransactionException;

    void rollback(TransactionStatus status) throws TransactionException;
}

1. 인터페이스 라는 것.
= 필요할 때 mock이나 stub을 만들어 사용할 수 있다. => 테스트 용이함.
= 인터페이스를 활용하여 구현 가능. => OOP 원칙 따름.

2. 위 인터페이스에 있는 모든 메소드에서 unchecked 예외를 발생시킨다는 것.
= 불 필요한 try-catch 문 사용 안 해도 됨.
= 물론 잡을 수 도 있지만 치명적이기 때문에 마땅히 할 수 있는 일도 없다. => 그냥 안 잡는게 타당함.

PlatformTransactionManager 인터페이스를 구현한 클래스들 입니다.[footnote]HibernateTransactionManager가 두 개 인데요. 이 중에 하나는 Hibernate 3쩜대 용입니다.[/footnote]

AbstractPlatformTransactionManager, CciLocalTransactionManager, DataSourceTransactionManager, HibernateTransactionManager, HibernateTransactionManager, JdoTransactionManager, JmsTransactionManager, JmsTransactionManager102, JpaTransactionManager, JtaTransactionManager, OC4JJtaTransactionManager, TopLinkTransactionManager, WebLogicJtaTransactionManager

첫번째에 있는 메소드를 좀 더 자세히 살펴보겠습니다.

인자로 TransactionDefinition 인터페이스를 넘겨 주고 TransactionStatus 인터페이스 타입의 객체를 받아 올 수 있습니다.

TransactionDefinition 인터페이스
에서 다음의 트랜잭션 속성을 설정할 수 있습니다.

Isolation: 다른 트랜잭션의 작업으로 부터 해당 트랜잭션이 얼마나 고립되어 있는지 정도.
ex) 다른 트랙잭션에 의해 쓰여졌지만 커밋은 되지 않은 것을 볼 수 있는가?

Propagation: 기존에 존재하는 트랜잭션 문맥이 있는 상태에서 어떻게 수행할지 선택할 수 있는 옵션.
ex1) 그냥 기존에 있는 트랜잭션 내에서 처리 한다.
ex2) 기존의 트랜잭션을 종료하고 새로운 트랜잭션에서 처리한다.

Timeout: 정해 준 시간이 지날 경우 타임 아웃 되며 자동으로 롤백 됩니다.

Read-only status: 이 상태로 설정해 주면 어떤 데이타도 수정할 수 없습니다. 최적화를 위해 유용하게 사용할 수 있습니다. (such as when using Hibernate).

TransactionStatus 인터페이스는 이름 그대로 트랜잭션의 상태에 관한 정보를 가져올 수 있고 예외를 발생하는 방법이 아닌 프로그래밍 적으로 롤백을 설정할 수 있습니다.

Transaction management

9.1. Introduction

트랜잭션 관리를 위한 추상화를 통해 다음의 장점들을 제공합니다.

  • JTA, JDBC, Hibernate, JPA, and JDO와 같은 다른 트랜잭션 관리 API 간에도 일관된 프로그래밍을 할 수 있습니다.
  • 선언적인 트랜잭션 관리를 할 수 있습니다.
  • JTA 같은 복잡한 방법이 아닌 단순한 API를 제공합니다.
  • Spring의 다양한 데이타 접근 추상화(data access abstractions)와 통합하기 좋습니다.

9.2. Motivations

EJB CMT 또는 Hibernate 같은 독자적인 API를 사용한 트랜잭션 관리 대신 Spring 프레임워크의 트랜잭션 추상화를 사용하기 원하는 이유에 대해 나옵니다.

9.3. Key abstractions

Spring 프레임워크의 트랜잭션 지원을 위한 핵심 클래스들을 소개하고 어떻게 설정하고 다양한 자원으로 부터 DataSource 객체를 얻을 수 있는지 설명합니다.

9.4. Resource synchronization with transactions

어떻게 어플리케이션 코드에서 직접적으로 또는 간접적으로 퍼시스턴트의 API를 사용할 수 있는지 설명합니다.

9.5. Declarative transaction management

Spring AOP를 사용하여 기존 코드에 가장 적은 영향을 주며 선언적으로 트랜잭션 관리를 할 수 있도록 하는 방법을 설명합니다.

9.6. Programmatic transaction management

프로그래밍을 통한 트랜잭션 관리 방법에는 TransactionTemplate 과 PlatformTransactionManager 사용하는 두 가지가 있는데 이 중에 첫번째 방법을 권장합니다.

9.7. Choosing between programmatic and declarative transaction management

선언적인방법과 프로그래밍을 통한 방법의 장단점을 살펴 봅니다.

9.8. Application server-specific integration

Spring 프레임워크의 트랜잭션 추상화는 일반적으로 서버를 인지 하지 못합니다. 부가적으로 특정 웹서버를 위한 클래스를 제공합니다.

9.9. Solutions to common problems

특정 DataSource를 위한 잘못된 트랜잭션 메니저 사용에 관한 내용이 있습니다.

9.10. Further Resources

This book,
Java Transaction Design Strategies
from InfoQ