Spring 트랜잭션 처리 1. Programmtic
참조 : Spring 프레임워크 워크북, 9.6. Programmatic transaction management (1)
레퍼런스와 워크북에도 나오지만 프로그래밍 적인 트랜잭션 처리 방법은 크게 두 가지가 있습니다.
1. PlatformTransactionManager, TransactionStatus, TransactionDefinition을 사용하는 방법
(1)TransactionManager를 만들 때는 사용하는 트랜잭션 자원에 따라 만드는 방법이 다릅니다. (2)그리고 TransactionManager로 부터 getTransaction을 사용하여 트랜잭션을 생성하게 되는데 이 때 TransactionStatus라는 객체를 받게 됩니다. (3)롤백과 커밋은 TransactionManager를 사용하며 이 때 Status객체를 넘겨줘야 합니다.
서비스 계층의 구현된 코드를 보면서 위의 내용을 살펴보겠습니다.
private MemberDao memberDao;
private PlatformTransactionManager transactionManager;
public void setMemberDao(MemberDao memberDao) {
this.memberDao = memberDao;
}
public void setTransactionManager(PlatformTransactionManager transactionManager) {
this.transactionManager = transactionManager;
}
public void add(Member member) throws SQLException {
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setName("멤버 추가하는 트랜잭션");
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
TransactionStatus status = transactionManager.getTransaction(def); //(2)
try {
memberDao.add(member);
//TODO 예외 발생
TransactionTestingUtil.generateExceptionMethod();
transactionManager.commit(status); //(3)
}
catch (MyException e) {
System.out.println(def.getName() + " 롤백합니다.");
transactionManager.rollback(status); //(3)
throw e;
}
}
}
TransactionManager는 HibernateTransactionManager 를 사용하고 있습니다. XML 설정을 보면 다음과 같습니다.
<property name="memberDao" ref="memberDao" />
<property name="transactionManager" ref="transactionManager" />
</bean>
<bean id="memberDao" class="com.bookbuying.member.dao.MemberDaoImpleWIthSpringTransaction">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean" autowire="no">
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses" ref="annotatedClasses" />
<property name="hibernateProperties">
<props>
<!-- 지금 사용하고 있는 데이터베에스에 최적화 된 SQL을 생성하기 위해서
현재 데이터베이스에 해당하는 Hibernate dialect 클래스 명 -->
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<!-- 콘솔 창에 사용하는 모든 SQL문을 출력할지를 선택 -->
<prop key="hibernate.show_sql">true</prop>
<!-- DB Schema에 변경사항이 발생한 경우 자동으로 수정 -->
<prop key="hibernate.hbm2ddl.auto">update</prop>
<!-- 성능 튜닝에 도움이 되는 유용한 통계를 제공 -->
<prop key=" hibernate.generate_statistics">true</prop>
<!-- 자동 커밋이 되는 것을 방지 -->
<prop key="hibernate.connection.autocommit">false</prop>
<!-- "Current" Session의 Scope 설정.<jta/thread/managed/custom> -->
<prop key="hibernate.current_session_context_class">thread</prop>
</props>
</property>
</bean>
<util:list id="annotatedClasses">
<value>com.bookbuying.domain.Member</value>
</util:list>
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager" autowire="no">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
주석은 친절한 하이버네이트 찬욱군이 달아 놓았습니다. Hibernate를 사용하여 DAO쪽 구현을 했습니다. 여기서 Session에 주목할 필요가 있습니다. 그건 다음 글에서 살펴보겠습니다.
private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public void add(Member member) {
Session session = sessionFactory.getCurrentSession();
session.save(member);
}
}