티스토리 뷰

728x90

이전에 step2에서 포인트컷 표현식과 트랜잭션 속성을 이용해 트랜잭션을 일괄적으로 적용하는 방식은 복잡한 트랜잭션 속성이 요구되지 않는 한 대부분의 상황에 적용가능하지만 클래스나 메소드에 다라 제각각 속성이 다른, 세밀하게 튜닝된 트랜잭션 속성을 적용해야 하는 경우 일괄적으로 속성을 부여하는 것 대신에 직접 타깃에 트랜잭션 속성정보를 가진 애노테이션을 이용하는 방법이 있다.

 

@Transactional을 정의한 코드는 직관적이라 이전에 설명한 속성을 모두 포함하고 있다.

pacakage org.springframwork.transaction.annotation;
...

@Target({ElementType.METHOD, ElementType.TYPE})
@Retension(RetentionPolicy.RUNTIME)
@Inherited
@Documented

public @interface Transactional {
	String value() default "";
    Propagation propagation() default Propagaion.REQUIRED;
    Isolation isolation() default Isolation.DEFAULT;
    int timeout() default TransactionDefinition.TIMEOUT_DEFAULT;
    boolean readOnly() defalut false;
    Class<? extends Throwable>[] rollbackFor() default {};
    String[] rollbackForClassName() default {};
    Class<? extends Throwable>[] noRollbackFor() default {};
    String[] noRollbackForClassName() default {};
}

@Transactional 애노테이션의 타깃은 메소드와 타입이다. 따라서 메소드, 클래스, 인터페이스에 사용가능하다. @Transactional 애노테이션을 트랜잭션 속성정보로 사용하도록 지정하면 @Transactional이 부여된 모든 오브젝트를 자동으로 타깃 오브젝트로 인식한다. 이 때 사용되는 포인트컷은 TransactionAttributeSourcePointcut이다. TransactionAttributeSourcePointcut은 스스로 표현식과 같은 선정기준을 가지고 있지 않고 이 애노테이션이 붙은 오브젝트를 모두 찾아서 포인트컷의 선정 결과로 돌려준다.

 

@Transactional을 이용한 트랜잭션 속성을 사용하는 것은 스프링이 모든 설정을 하나의 태그에 담아뒀기 때문에 필요한 어드바이저, 어드바이스, 포인트컷, 애노테이션을 이용하는 트랜잭션 속성 정보가 등록된다. 

<tx:annotation-driven/>

@Transactional의 경우 메소드 레벨이 가장 큰 우선순위를 가지기 때문에 기본적으로 Service 단에서 작업할 경우 클래스 레벨에 @Transactional(readOnly=true)를 지정하고 데이터 처리작업에 @Transactional을 새로 정의해서 쓰는 것이 효율적인 방법이라고 볼 수 있다. 

@Transactional(readOnly=true)
public interface UserService {
	@Transactional
	void add(User user);
    
    @Transactional
	void delete(User user);
    
	User get(String id);
    List<User> getAll();
}

반대로 클래스레벨에 @Transactional를 지정해줬으면 읽기 전용에 따로 readOnly=true 속성을 적용해주어도 상관없다. 

 

일부 메소드에만 트랜잭션이 필요하다면 메소드 레벨에 @Transactional을 적용하면 된다. 반면에 대부분의 메소드에서 트랜잭션이 필요하다면 클래스에 @Transactional을 지정하는 것이 편리하다. 그런 경우 굳이 트랜잭션이 필요없는 메소드는 어떻게 해야할까? @NotTransactional이 기존에 존재했지만 스프링 3.0에서 제거대상이기 때문에 전파 속성을 이용하는 방법이 있다. 다음과 같이 NAVER 전파 속성을 지정해주면 트랜잭션이 시작하지 않을 것이다.

@Transactional(propagation=Propagation.NEVER)

 

추가적으로 테스트 메소드나 클래스에서 사용하는 @Transactional은 애플리케이션의 클래스에 적용할 때와 디폴트 속성은 동일하지만 중요한 차이점이 하나 있는데 테스트용 트랜잭션은 테스트가 끝나면 자동으로 롤백이 된다는 것이다. 원하지 않을 경우 @Rollback(false) 옵션을 메소드 레벨에 추가하거나 클래스 레벨에 @TransactionConfiguration(defaultRollback=false)를 추가해주어도 된다. 이는 롤백 여부에 대한 기본 설정과 트랜잭션 매니저 빈 등의 설정을 지정하는데 사용할 수 있다. 기본값은 transactionManager를 사용한다.

 

 

 

 

 

 

 

 

참고 자료 - 토비의 스프링 3.1 | 저자 이일민

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/07   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
글 보관함