Programming/Spring Framework
Spring JUnit Test + iBatis의 Transaction 관리
otamot
2008. 2. 14. 13:24
SpringJUnit4ClassRunner을 기반으로 iBatis DAO객체를 테스트 중입니다. insert 테스트중에 알 수 없는 현상이 발생했습니다. insert 수행에서 오류는 발생하지 않았는데 DB에는 INSERT 되지 않더군요. iBatis의 auto commit 설정을 살펴보니 sqlMap설정에서 transactionManager를 설정하지 않고 외부 dataSource를 사용하게 되면 auto_commit는 자동으로 되지 않는다고. 현재 저는 Spring 에서 설정되어 있습니다.
위와 같이 되어 있고 설정에는 문제가 없었습니다. DAO에서 insert 함수는 'insertContent(...)'로 올바르게 설정되어 있습니다. 오류도 나지 않고 DB에는 insert되지 않고... 난감했습니다. 답은 log에 있었습니다. 다음과 같은 log가 찍혀있었습니다.
간단히 말해서 test execution이기 때문에 rollback이 수행 된 것입니다. INSERT문으로 입력을 했더니 AUTO_INCREAMENT 항목이 많이 증가해 있었습니다. INSERT 수행수 Rollback을 계속해서 수행했던 것입니다. 똑똑합니다. 그렇다면 Test시에는 어떻게 해야 할까요. 결국 찾은 것은 다음과 같습니다.
Test 클래스에 다음가 같은 Annotation 설정이 있습니다.
@TransactionConfiguration의 attribute에서 defaultRollback속성이 있는데 현재 true로 설정되어 있습니다. rollback처리를 하겠다는 뜻입니다. 이것을 false로 변경하면 rollback 처리를 하지 않겠다는 뜻이겠지요?
다음은 테스트 결과 log입니다.
rollback이 false로 commit처리 되었습니다. DB에도 insert된 결과를 확인 했습니다.
iBatis의 transaction 수행을 code상에서 수행 할 때 기본 설정과 달리 수행해고 싶을 때 다음과 같이 작성합니다.
이렇게 하면 transaction 시작 point와 종료 point를 새로 구성되게 되는 것입니다. 위의 결과 로그를 보면 'Begin transaction'이란 문구가 있습니다. 같은 작용하고 있는 것 같습니다.
코드 작성시 기존 transaction 설정을 따르게 하고 싶으면 위 코드에서 sqlMap.startTransaction();와 sqlMap.commitTransaction();를 제거 하면 됩니다.
<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>
<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)
@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].
[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();
List list = sqlMap.queryForList (“getProductList”, null);
sqlMap.commitTransaction();
이렇게 하면 transaction 시작 point와 종료 point를 새로 구성되게 되는 것입니다. 위의 결과 로그를 보면 'Begin transaction'이란 문구가 있습니다. 같은 작용하고 있는 것 같습니다.
코드 작성시 기존 transaction 설정을 따르게 하고 싶으면 위 코드에서 sqlMap.startTransaction();와 sqlMap.commitTransaction();를 제거 하면 됩니다.
List list = sqlMap.queryForList (“getProductList”, null);