참조 : Spring 프레임워크 워크북, 9.6. Programmatic transaction management (1)

레퍼런스와 워크북에도 나오지만 프로그래밍 적인 트랜잭션 처리 방법은 크게 두 가지가 있습니다.

1. PlatformTransactionManager, TransactionStatus, TransactionDefinition을 사용하는 방법

(1)TransactionManager를 만들 때는 사용하는 트랜잭션 자원에 따라 만드는 방법이 다릅니다. (2)그리고 TransactionManager로 부터 getTransaction을 사용하여 트랜잭션을 생성하게 되는데 이 때 TransactionStatus라는 객체를 받게 됩니다. (3)롤백과 커밋은 TransactionManager를 사용하며 이 때 Status객체를 넘겨줘야 합니다.

서비스 계층의 구현된 코드를 보면서 위의 내용을 살펴보겠습니다.

public class MemberServiceImplWithSpringTransaction implements MemberService {

    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 설정을 보면 다음과 같습니다.

    <bean id="memberService" class="com.bookbuying.member.service.MemberServiceImplWithSpringTransaction">
        <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에 주목할 필요가 있습니다. 그건 다음 글에서 살펴보겠습니다.

public class MemberDaoImpleWIthSpringTransaction implements MemberDao{

    private SessionFactory sessionFactory;

    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    public void add(Member member) {
        Session session = sessionFactory.getCurrentSession();
        session.save(member);
    }
}