상세 컨텐츠

본문 제목

Spring JUnit Test + iBatis의 Transaction 관리

Programming/Spring Framework

by otamot 2008. 2. 14. 13:24

본문

  SpringJUnit4ClassRunner을 기반으로 iBatis DAO객체를 테스트 중입니다. insert 테스트중에 알 수 없는 현상이 발생했습니다. insert 수행에서 오류는 발생하지 않았는데 DB에는 INSERT 되지 않더군요. iBatis의 auto commit 설정을 살펴보니 sqlMap설정에서 transactionManager를 설정하지 않고 외부 dataSource를 사용하게 되면 auto_commit는 자동으로 되지 않는다고. 현재 저는 Spring 에서 설정되어 있습니다.
    <bean id="mysqlTxProxyTemplate" abstract="true" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
        <property name="transactionManager" ref="mysqlTransactionManager"/>
        <property name="transactionAttributes">
            <props>
                <prop key="insert*">PROPAGATION_REQUIRED</prop>
                <prop key="update*">PROPAGATION_REQUIRED</prop>
                <prop key="delete*">PROPAGATION_REQUIRED</prop>
                <prop key="execute*">PROPAGATION_REQUIRED</prop>
                <prop key="get*">PROPAGATION_REQUIRED</prop>
                <prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
            </props>
        </property>
    </bean>

  위와 같이 되어 있고 설정에는 문제가 없었습니다. DAO에서 insert 함수는 'insertContent(...)'로 올바르게 설정되어 있습니다. 오류도 나지 않고 DB에는 insert되지 않고... 난감했습니다. 답은 log에 있었습니다. 다음과 같은 log가 찍혀있었습니다.
[COTAMOT]  INFO,[2008-02-14 13:10:16,912],[main],(TransactionalTestExecutionListener.java:355),Rolled back transaction after test execution for test context [[TestContext@1b273cc testClass = ContentTest, locations = array<String>['file:web/WEB-INF/config/applicationContext*.xml'], testInstance = test.spring.test.ContentTest@76e8a7, testMethod = TestGetContentList@ContentTest, testException = [null]]].

  간단히 말해서 test execution이기 때문에 rollback이 수행 된 것입니다. INSERT문으로 입력을 했더니 AUTO_INCREAMENT 항목이 많이 증가해 있었습니다. INSERT 수행수 Rollback을 계속해서 수행했던 것입니다. 똑똑합니다. 그렇다면 Test시에는 어떻게 해야 할까요. 결국 찾은 것은 다음과 같습니다.
  Test 클래스에 다음가 같은 Annotation 설정이 있습니다.
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration (locations={"file:web/WEB-INF/config/applicationContext*.xml"})
@TransactionConfiguration (transactionManager="mysqlTransactionManager", defaultRollback=true)

  @TransactionConfiguration의 attribute에서 defaultRollback속성이 있는데 현재 true로 설정되어 있습니다. rollback처리를 하겠다는 뜻입니다. 이것을 false로 변경하면 rollback 처리를 하지 않겠다는 뜻이겠지요?
다음은 테스트 결과 log입니다.
[COTAMOT]  INFO,[2008-02-14 13:16:22,007],[main],(TransactionalTestExecutionListener.java:348),Committed transaction after test execution for test context [[TestContext@1d3cdaa testClass = ContentTest, locations = array<String>['file:web/WEB-INF/config/applicationContext*.xml'], testInstance = test.spring.test.ContentTest@15718f2, testMethod = insertContent@ContentTest, testException = [null]]].
[COTAMOT]  INFO,[2008-02-14 13:16:22,017],[main],(TransactionalTestExecutionListener.java:314),Began transaction (2): transaction manager [org.springframework.jdbc.datasource.DataSourceTransactionManager@1e7c5cb]; rollback [false]; flagged for commmit [true].

  rollback이 false로 commit처리 되었습니다. DB에도 insert된 결과를 확인 했습니다.
  iBatis의 transaction 수행을 code상에서 수행 할 때 기본 설정과 달리 수행해고 싶을 때 다음과 같이 작성합니다.
sqlMap.startTransaction();
List list = sqlMap.queryForList (“getProductList”, null);
sqlMap.commitTransaction();

이렇게 하면 transaction 시작 point와 종료 point를 새로 구성되게 되는 것입니다. 위의 결과 로그를 보면 'Begin transaction'이란 문구가 있습니다. 같은 작용하고 있는 것 같습니다.
  코드 작성시 기존 transaction 설정을 따르게 하고 싶으면 위 코드에서 sqlMap.startTransaction();와 sqlMap.commitTransaction();를 제거 하면 됩니다.
List list = sqlMap.queryForList (“getProductList”, null);

관련글 더보기