MyBatis | 배치(batch) 갱신

기본적으로 SQL을 실행할 때마다 PreparedStatement를 생성하여 SQL을 데이터베이스에 전송하고 있다.

업데이트 건수가 많은 경우, 이것은 매우 효율이 나쁘다.

MyBatis는 설정에 따라 PreparedStatement의 재사용과 배치 갱신이 가능하게 되어있다.

기본 동작

소스 코드

sample_mapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="sample.mybatis">

  <insert id="insertTest">
    insert into test_table (value) values (#{value})
  </insert>
</mapper>

Main.java

package sample.mybatis;

import java.io.InputStream;

import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

public class Main {

    public static void main(String[] args) throws Exception {
        try (InputStream in = Main.class.getResourceAsStream("/mybatis-config.xml")) {
            SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);

            try (SqlSession session = factory.openSession()) {
                for (int i=0; i<3; i++) {
                    TestTable t = new TestTable("value-" + i);
                    int updateCount = session.insert("sample.mybatis.insertTest", t);
                    System.out.println("updateCount = " + updateCount);
                }

                session.commit();
            }
        }
    }
}
  • 3회 반복하여 INSERT를 실행하도록 구현하였다.

실행 결과

[DEBUG] s.m.insertTest  - ==>  Preparing: insert into test_table (value) values (?) 
[DEBUG] s.m.insertTest  - ==> Parameters: value-0(String)
[DEBUG] s.m.insertTest  - <==    Updates: 1
updateCount = 1
[DEBUG] s.m.insertTest  - ==>  Preparing: insert into test_table (value) values (?) 
[DEBUG] s.m.insertTest  - ==> Parameters: value-1(String)
[DEBUG] s.m.insertTest  - <==    Updates: 1
updateCount = 1
[DEBUG] s.m.insertTest  - ==>  Preparing: insert into test_table (value) values (?) 
[DEBUG] s.m.insertTest  - ==> Parameters: value-2(String)
[DEBUG] s.m.insertTest  - <==    Updates: 1
updateCount = 1

설명

  • 매번 PreparedStatement가 생성되어 SQL이 전송되고 있다.

PreparedStatement을 재이용한다.

소스 코드

mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
  <settings>
    <setting name="defaultExecutorType" value="REUSE"/>
  </settings>

  ...
</configuration>

실행 결과

[DEBUG] s.m.insertTest  - ==>  Preparing: insert into test_table (value) values (?) 
[DEBUG] s.m.insertTest  - ==> Parameters: value-0(String)
[DEBUG] s.m.insertTest  - <==    Updates: 1
updateCount = 1
[DEBUG] s.m.insertTest  - ==> Parameters: value-1(String)
[DEBUG] s.m.insertTest  - <==    Updates: 1
updateCount = 1
[DEBUG] s.m.insertTest  - ==> Parameters: value-2(String)
[DEBUG] s.m.insertTest  - <==    Updates: 1
updateCount = 1

설명

  • 설정 파일에서 defaultExecutorType에 REUSE를 설정한다.
  • PreparedStatement가 한번만 생성된다.
  • SQL의 전송은 매번 이루어지고 있다.

배치 실행

소스 코드

mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
  <settings>
    <setting name="defaultExecutorType" value="BATCH"/>
  </settings>

  ...
</configuration>

실행 결과

[DEBUG] s.m.insertTest  - ==>  Preparing: insert into test_table (value) values (?) 
[DEBUG] s.m.insertTest  - ==> Parameters: value-0(String)
updateCount = -2147482646
[DEBUG] s.m.insertTest  - ==> Parameters: value-1(String)
updateCount = -2147482646
[DEBUG] s.m.insertTest  - ==> Parameters: value-2(String)
updateCount = -2147482646

설명

  • defaultExecutorType를 BATCH로 하면 일괄 업데이트된다.
  • SQL의 전송은 마지막으로 함께 진행된다.
  • 그래서, 업데이트 건수는 얻을 수 없게 되어있다.

SqlSession을 얻을 때 지정한다.

배치 갱신할지 여부의 설정은 SqlSession을 얻을 때의 인수로 지정할 수 있다.

import org.apache.ibatis.session.ExecutorType;

...

SqlSession session = factory.openSession(ExecutorType.BATCH);

openSession()의 인수에 ExecutorType를 전달하여 지정할 수 있다. 여기에 지정된 조건은 설정 파일보다 우선된다.

최종 수정 : 2021-08-26