달력

3

« 2024/3 »

  • 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
2013. 8. 6. 11:56

spring transactionManager 설정 I.lib()/I.lib(Spring)2013. 8. 6. 11:56

.. .. ..

[펌] : http://springmvc.egloos.com/499291

 

 

<tx:annotation-driven />
<aop:config>
<aop:advisor advice-ref="transactionAdvice" pointcut="bean(*Service)" />
</aop:config>

<tx:advice id="transactionAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="exceptionPut" propagation="REQUIRES_NEW" />
<tx:method name="get*" propagation="REQUIRED" read-only="true" />
<tx:method name="*" />
</tx:attributes>
</tx:advice>

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>

전 장에서 <aop>까지 했으니 이제 <tx> 요소에 대해 설명할 차례네요. <tx>는 스프링 트랜잭션 기술의 집약체입니다. 스프링의 트랜잭션 기술은 전장에서도 말했듯이 어노테이션 적용법과 AOP 적용법 2가지가 있으며 위의 예제는 당연히 AOP 적용법입니다.

먼저 <tx:advice>로 트랜잭션 어드바이스를 하나 만듭니다. 여기에 적용한 트랜잭션을 선택하는데 만약 트랜잭션 빈의 이름이 'transactionManager'이라면 위의 'transaction-manager' 속성은 생략될 수 있습니다. 위의 예제에서는 다만 원리를 설명하기 위해 속성을 넣어둔 것 뿐이므로 현재 'transaction-manager'은 생략이 가능하다 할 수 있겠네요.

그다음 <tx:attributes>의 <tx:method>로 세밀하게 메서드별 속성을 조절해주도록 합시다. 우리는 이 부분에서 어느 메서드에 트랜잭션을 적용할 것인지 선택할 수 있으며 속성에는 다음과 같은 값들이 존재합니다.

name - 메서드명
메서드의 이름이며 와일드 문자(*)를 사용할 수 있습니다. 예로 'get*'은 get으로 시작하는 모든 메서드를 가리키며'*get'은 get으로 끝나는 모든 메서드를 가리킵니다.

timeout - 제한시간 (기본값 : -1)
트랜잭션의 제한시간을 설정합니다. DB가 해당기능을 지원해야 하며 기본값으로는 -1인 제한시간 없음이 설정됩니다.

propagation - 전파옵션 (기본값 : REQUIRED)
REQUIRED : 부모 트랜잭션 내에서 실행하며 부모 트랜잭션이 없을 경우 새로운 트랜잭션을 생성합니다.
REQUIRES_NEW : 부모 트랜잭션을 무시하고 무조건 새로운 트랜잭션이 생성되도록 합니다.
SUPPORT : 부모 트랜잭션 내에서 실행하며 부모 트랜잭션이 없을 경우 nontransactionally로 실행됩니다.
MANDATORY : 부모 트랜잭션 내에서 실행되며 부모 트랜잭션이 없을 경우 예외가 발생됩니다.
NOT_SUPPORT : nontransactionally로 실행하며 부모 트랜잭션 내에서 실행될 경우 일시 정지 됩니다.
NEVER : nontransactionally로 실행되며 부모 트랜잭션이 존재한다면 예외가 발생합니다.
NESTED : 해당 메서드가 부모 트랜잭션에서 진행될 경우 별개로 커밋되거나 롤백될 수 있습니다. 둘러싼 트랜잭션이 없을 경우 REQUIRED와 동일하게 작동합니다.

isolation - 격리수준 (기본값 : DEFAULT)

DEFAULT : DB에서 설정된 기본 격리 수준을 따릅니다.
SERIALIZABLE : 가장 높은 격리수준을 가지며 사용시 성능 저하가 있을 수 있습니다.
READ_UNCOMMITTED : 커밋되지 않은 데이터에 대한 읽기를 허용합니다.
READ_COMMITTED : 커밋된 트랜잭션에 대해 읽기를 허용합니다.
REPEATABLE_READ : 동일한 필드에 대한 다중 접근 시 동일한 결과를 얻을 수 잇는 것을 보장합니다.

read-only - 읽기전용 (기본값 : false)

해당 메서드는 오로지 읽기에만 사용됩니다. INSERT나 UPDATE, DELETE문은 허용되지 않습니다. 만약 쓰기나 삭제가 실행될 경우 에러를 발생시킵니다.

rollback-for - 예외처리 (기본값 : RuntimeException)

특정 예외가 발생했을 경우에 롤백되도록 설정합니다. 설정하지 않을 경우 오로지 RuntimeException을 상속받은 예외에만 롤백처리를 해줍니다.

no-rollback-for - 예외처리 (기본값 : 없음)

특정 예외가 발생하더라도 롤백되지 않도록 설정합니다.

위의 속성과 값들이 <tx:method>에서 설정할 수 있는 전부입니다. 잘 알아본 다음 자신에게 맞는 속성을 설정한 후에 완성된 <tx:advice>를 <aop:config>에 주입하기만 하면 자동프록시검색기가 알아서 <tx>어드바이스와 pointcut을 해석하여 해당 요청을 대신 처리해 줄 것입니다.

이제 거의 막바지에 왔네요. 다음은 <tx:annotation-driven />에 대한 설명입니다. 이 요소가 설정되있다면 트랜잭션을 어노테이션으로 설정 가능하게 합니다. 설정방법은 트랜잭션을 원하는 메서드에 @Transactional이란 어노테이션을 붙이면 그만이며 <aop>설정은 어노테이션과 전혀 무관합니다. 어노테이션 트랜잭션은 오로지 <tx:annotation-driven /> 요소만을 요구합니다.

@Transactional(isolation=Isolation.DEFAULT, propagation=Propagation.REQUIRES_NEW)

어노테이션으로 트랜잭션으로 설정하는 방법은 직관적이고 알기 쉽지만 수정이 필요할 때에는 코드 자체를 수정해야 한다는 단점이 있습니다. 위의 예시처럼 어노테이션도 <tx:method>와 같이 똑같은 옵션설정이 가능합니다. 설정방법은 이클립스의 자동완성기능(CTRL + F1)으로 알아보시면 편리하니 따로 설명하지는 않겠습니다 :D

일단 어노테이션으로 트랜잭션을 설정할 시 주의할 점은 가장 우선적으로 고려되는 순서가 있다는 것입니다. 만약 인터페이스 - 클래스 - 메서드 모두에 트랜잭션 어노테이션이 설정되있다면 스프링은 메서드 어노테이션을 제일 먼저 고려하고 그 다음이 클래스, 인터페이스 순서으로 적용합니다. 개인적으로는 가급적 어드바이스를 활용해 트랜잭션 경계를 설정하는 게 좋다고 생각하는데 어노테이션 트랜잭션을 남발할 경우 작성된 프레임워크의 잦은 수정이 불가피해지기 때문입니다.

트랜잭션도 상황에 따라 자주 설정이 변경되어줘야 하는데 어노테이션으로 설정을 고정해버리고 매번 수정이 필요할 때마다 소스자체를 바꾸다보면 다른 코드에 영향을 줄 수도 있고 이용하는 사람 입장에서도 상당히 불편할 수 있습니다. 가급적 어드바이스로 트랜잭션 경계를 설정하고 정말 불변하는 트랜잭션에 대해서만 어노테이션을 이용하길 권장합니다.


이제 마지막으로 트랜잭션 매니저 설정을 위한 PlatformTransactionManager을 설명하고 끝마치려 합니다 ^^. 스프링은 다양한 플랫폼과 환경에서도 완벽하게 트랜잭션 클래스들의 DI가 가능 하도록 PlatformTransactionManager 인터페이스를 갖고 있다는 사실을 알고 계신가요?

우리가 구현했던 소스에서는 볼 수 없었지만 분명 <tx:advice>를 구성하는 소스에는 PlatformTransactionManager 인터페이스를 통해 구현 클래스의 주입을 요구하고 있습니다. 현재의 소스는 제가 JDBC/MyBatis를 이용하고 있으므로 위의 예제와 같이 DataSrouceTransactionManager 클래스를 이용해 트랜잭션 매니저를 구현했지만 만약 하이버네트나 JTA같은 다른 플랫폼을 이용할 경우에도 소스에 변경 일절 없이 오로지 트랜잭션 매니저만 변경해주면 간편하게 모든 설정을 끝마칠 수 있습니다.

이렇게 트랜잭션에 대한 모든 설명이 끝났네요. 사실 부족한 부분이 많지만 이정도면 스프링에서 어떻게 트랜잭션을 설정하였고 활용방안에 대한 감을 잡을 수 있다는 생각이 듭니다. 부족한 부분이나 이해가 안가시는 부분은 피드백 주시구요. 다음에 좀 더 좋은 포스트로 찾아올게요 ^^
.
:
Posted by .07274.