IT_Programming/Dev Libs & Framework

[펌] Spring + iBatis 연동시 iBatis Transaction 실행 안되는 문제

JJun ™ 2013. 4. 5. 18:42

 


출처: http://javastore.tistory.com/103


 



프로젝트를 진행하다 Transaction을 수행해야 하는 query가 있었습니다.

그때 저는 iBatis의 Transaction을 통해 다음과 같이 구현하였습니다.
(Spring에서 제공하는 SqlMapClientTemplate를 이용하여 iBatis를 사용했습니다)

 

 

 SqlMapClient sqlClient = template.getSqlMapClient();
 try

 {
     sqlClient.startTransaction();
     template.insert("turotial.dataInsert", data);
     template.insert("tutorial.updateInfo", data);
     sqlClient.commitTransaction();
     return true;
}

catch (SQLException e)

{
     e.printStackTrace();
     return false;
}

finally

{
     sqlClient.endTransaction();
}

 

 

위와 같이 insert하고 update부분을 iBatis의 transaction으로 묶으려고 하였습니다.

하지만 우연치 않게 iBatis의 Transaction이 먹히지 않는것을 발견하였습니다.

왜이럴까 고민하다가 Spring에서 제공하는 Transaction을 통해 구현해 보기로 하였고,

결국 Transaction이 제대로 동작하는것을 확인 할 수 있었습니다.

저같은 경우는 Spring project를 할때 db연동에 관련한 모든 bean들을

applicationContext-iBatis.xml에 몰아 둡니다. (관리하기가 더 편하더라구요.. 개인적 생각입니다.^^)

저는 이 ibatis.xml 에 ibatis를 통해 DB에 접근할 dataSource bean을 설정해 두었습니다.

1. transactionManager와 transactionTemplate을 bean으로 등록합니다.

 

<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
        <property name="jndiName" value="java:comp/env/jdbc/tutorial"/>
</bean>
 
<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
       <property name="configLocation" "classpath:sqlMapConfig.xml" />
       <property name="dataSource" ref="dataSource" />
</bean>
 
<bean id="template"
          class="org.springframework.orm.ibatis.SqlMapClientTemplate"
          p:sqlMapClient-ref="sqlMapClient"/>
   
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
p:dataSource-ref="dataSource"/>
   
<bean id="transactionTemplate" 
      class="org.springframework.transaction.support.TransactionTemplate"
      p:transactionManager-ref="transactionManager"/>

 

 

위와 같이 transactionManager와 transactionTemplate bean을 dataSource를 통해 생성합니다.

2. transactionTemplate를 사용할 bean에 property로 설정합니다.

 

 <bean id="tutorialDAO" class="tutorial.TutorialDAOImpl">
     <property name="template" ref="template"/>
     <property name="transactionTemplate" ref="transactionTemplate"/>
 </bean>

 

 

3. 해당 DAOImpl 클래스에서 field로 transactionTemplate와 setter method를 구현하여 DI가 되도록

    작업해 줍니다.

4. 다음과 같이 transactionTemplate를 통해 transaction을 구현합니다.

 

public boolean transactionTest(final TutirialVO vo ) throws SQLException

{
    boolean result = false;
    result = (Boolean)transactionTemplate.execute( new TransactionCallback()

    {
            public Object doInTransaction(TransactionStatus status)

            {
                      try

                      {
                          template.insert("Tutorial.insertData", vo);
                          template.insert("Tutorial.updateData", vo);
                          return true;
                      }

                      catch (Exception e)

                      {
                          e.printStackTrace();
                          status.setRollbackOnly();
                          return false;
                       }
             }
    });
 

    return result;

 

 

위와 같이 transactionTemplate.execute를 실행하고 전달인자로 TransactionCallBack 인스턴스를 전달하는데, 일반적으로 TransactionCallback이 인터페이스 이기 때문에 new로 객체를 생성하고 doInTransaction method를 구현합니다.