본문 바로가기
Programing/Spring

MyBatis 를 이용하여 executeBatch 처리하기

by Tomining 2016. 6. 22.
ibatis 를 이용하여 sql 을 묶음으로 처리 할 수 있었던 executeBatch() 를 MyBatis 에서는 어떻게 할 수 있을까요?

ibatis 와 유사하게 아래와 같이 진행할 수 있습니다.


@Configuration
@MapperScan(basePackages = "com.mybatis.mapper", sqlSessionTemplateRef = "sqlSessionTemplate")
public class MyBatisConfig {
   @Autowired
   private DataSource dataSource;

   @Bean(name = "sqlSessionFactoryBean")
   public SqlSessionFactoryBean sqlSessionFactoryBean() throws Exception {
      SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
      sessionFactory.setDataSource(dataSource);

      sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/*.xml"));
      return sessionFactory;
   }

   @Bean(name = "sqlSessionTemplate")
   @Primary
   public SqlSessionTemplate sqlSessionTemplate() throws Exception {
      return new SqlSessionTemplate(sqlSessionFactoryBean().getObject());
   }

   @Bean(name = "batchSqlSessionTemplate")
   public SqlSessionTemplate batchSqlSessionTemplate() throws Exception {
      return new SqlSessionTemplate(sqlSessionFactoryBean().getObject(), ExecutorType.BATCH);  // ExecuteType 을 Batch 로 지정
   }
}
@Override
public int batchExecute(Map<String, Object> params) throws Exception {
    ...

    for (::) {
        ...
        
        batchSqlSessionTemplate.update(“mapper.updateInfos", params);
       
        … 
    }

    batchSqlSessionTemplate.flushStatements();

    ...
}

SessionTemplate 을 생성할 때, ExecuteType 을 지정할 수 있으며, 이를 BATCH 타입으로 지정하면 됩니다.

한 번 실행해 봅시다.


“Create a new SqlSession 로그를 확인 할 수 있습니다.
의도 했던 대로라면 동일 SqlSession 으로 묶음 처리를 할 것이라고 예상하였으나, 정상적으로 이뤄지지 않음을 확인할 수 있습니다.

SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2adea61c] was not registered for synchronization because synchronization is not active

추가적으로 위와 같은 로그도 함께 보입니다.
Transaction이 정상적으로 적용이 되지 않아 발생하는 것으로 Transaction처리가 적용되어야 합니다.

Transaction 설정이 되어 있어야 합니다.
만약 @Transactional 을 적용하고자 하는 경우 2가지 방법으로 진행할 수 있습니다.
1. JavaConfig
    @EnableTransactionManagement

2. ApplicationContext
    <tx:annotation-driven proxy-target-class=“true”/>
묶음처리를 적용하고자 하는 메소드에 @Transactional 옵션을 붙여줍니다.

@Transactional
@Override
public int batchExecute(Map<String, Object> params) throws Exception {
    ...

    for (::) {
        ...
        
        batchSqlSessionTemplate.update(“mapper.updateInfos", params);
       
        … 
    }

    batchSqlSessionTemplate.flushStatements();

    ...
}

다시 수행해 보면 아래와 같이 수행할 수 있습니다.


현재 Transaction 에서 SqlSession 을 가져와 묶음 처리가 되며, 마지막에 Transaction commit 시 적용되는 것을 확인할 수 있습니다.
Debug 모드를 이용하여 DB 데이터와 함께 확인해 보면 정상적으로 묶음처리가 됨을 알 수 있습니다.


묶음처리 @Transaction 처리는 어찌보면 당연합니다.
묶음처리란 한 번에 묶음별로 DB에 반영됨을 의미하는데, 이를 Transaction 처리없이 적용하는 것은 의미가 없기 때문입니다.
당연하다고 생각할 수 있지만, 의외로 많이 놓치는 부분입니다.