MyBatis | Batch Updates

By default, each time SQL is executed, a PreparedStatement is created and the SQL is sent to the database.

When there are many updates, this is very inefficient.

Depending on the configuration, MyBatis can reuse PreparedStatement instances and perform batch updates.

Default Behavior

Source Code

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();
            }
        }
    }
}
  • This implementation repeats INSERT three times.

Execution Result

[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

Description

  • A PreparedStatement is created and SQL is sent every time.

Reuse PreparedStatement

Source Code

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>

Execution Result

[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

Description

  • Set defaultExecutorType to REUSE in the configuration file.
  • The PreparedStatement is created only once.
  • SQL is still sent every time.

Batch Execution

Source Code

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>

Execution Result

[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

Description

  • Setting defaultExecutorType to BATCH performs batch updates.
  • SQL is sent together at the end.
  • As a result, the update count cannot be obtained.

Specify It When Obtaining SqlSession

The setting that determines whether to use batch updates can be specified as an argument when obtaining a SqlSession.

import org.apache.ibatis.session.ExecutorType;

...

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

You can specify it by passing ExecutorType to the argument of openSession(). The condition specified here takes precedence over the configuration file.