Batch Query
비즈니스 로직을 처리하다보면 다수의 데이터를 반복적으로 INSERT 혹은 UPDATE 해야 하는 경우가 생긴다. (일반적으로는 엑셀 업로드를 통한 데이터 밀어넣기(?) 같은 경우가 있다)
이 때 Service 레벨에서 List 나 Array 타입으로 데이터를 받아온 후 반복문을 통해 처리하는게 일반적인데, 적은 양의 데이터라면 큰 문제가 없으나, 100건만 넘어가버려도 서비스 성능에 큰 부하가 걸리게 된다.
웹서비스와 DB 간에 핑퐁을 오가며 100+건의 데이터를 전달한다는 건 서비스 입장에서는 상당한 I/O Delay 를 초래할 수 있으므로, 이를 해결하기 위한 Mybatis ExecutorType 중 Batch 에 대해 알아보자.
- DataSourceConfig.java
package com.hotsse.sample;
import javax.sql.DataSource;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class DataSourceConfig {
/**
* DataSource 객체 생성
*
* @methodName dataSource
* @return
*/
@Bean(name = "dataSource")
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}
/**
* SqlSessionFactory 객체 생성
*
* @methodName sqlSessionFactory
* @param dataSource
* @param applicationContext
* @return
* @throws Exception
*/
@Bean(name = "sqlSessionFactory")
public SqlSessionFactory sqlSessionFactory(@Qualifier("dataSource") DataSource dataSource, ApplicationContext applicationContext) throws Exception {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
sqlSessionFactoryBean.setMapperLocations(applicationContext.getResources("classpath*:mybatis/mapper/**/*.xml"));
sqlSessionFactoryBean.setTypeAliasesPackage("**.vo");
return sqlSessionFactoryBean.getObject();
}
/**
* SqlSessionTemplate 객체 생성
* @methodName sqlSessionTemplate
* @param sqlSessionFactory
* @return
* @throws Exception
*/
@Bean(name = "sqlSessionTemplate")
public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) throws Exception {
return new SqlSessionTemplate(sqlSessionFactory);
}
/**
* SqlSessionTemplate 객체 생성(Batch 전용)
* @methodName sqlSessionTemplate
* @param sqlSessionFactory
* @return
* @throws Exception
*/
@Bean(name = "batchSqlSessionTemplate")
public SqlSessionTemplate batchSqlSessionTemplate(SqlSessionFactory sqlSessionFactory) throws Exception {
return new SqlSessionTemplate(sqlSessionFactory, ExecutorType.BATCH);
}
}
- DataSourceConfig.java
package com.hotsse.sample;
import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Repository;
@Repository
public class TestDao {
@Autowired
@Qualifier("sqlSessionTemplate")
protected SqlSession sqlSession;
@Autowired
@Qualifier("batchSqlSessionTemplate")
protected SqlSession batchSqlSession;
// Batch 없는 버전
public void insert() {
for(int i=0; i<1000; i++) {
this.sqlSession.insert("your.insert.query");
}
}
// Batch 있는 버전 (월등히 빠를 것이다)
public void insertBatch() {
for(int i=0; i<1000; i++) {
this.batchSqlSession.insert("your.insert.query");
}
this.batchSqlSession.flushStatements();
}
}