MyBatis | バッチ更新
デフォルトでは、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は1回だけ作成される。
- 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を渡して指定できる。
ここで指定した条件は設定ファイルより優先される。