MyBatis 透過 <foreach> 標籤支援集合參數遍歷,配合批次 SQL 語法,能大幅提升大量資料寫入效能。本文整理三大批次操作實戰範例。
<insert id="batchInsertStudent" parameterType="java.util.List">
INSERT INTO student (id, name, sex, tel, address)
VALUES
<foreach collection="list" item="item" index="index" separator=",">
(#{item.id}, #{item.name}, #{item.sex}, #{item.tel}, #{item.address})
</foreach>
</insert>
public void batchInsertStudent() {
List<Student> list = new ArrayList<>();
for (int i = 5; i < 8; i++) {
Student s = new Student();
s.setId(i);
s.setName("maoyuanjun" + i);
s.setSex("man" + i);
s.setTel("tel" + i);
s.setAddress("浙江省" + i);
list.add(s);
}
try (SqlSession session = sqlSessionFactory.openSession()) {
session.insert("mybatisdemo.domain.Student.batchInsertStudent", list);
session.commit();
}
}
<update id="batchUpdateStudent" parameterType="java.util.List">
UPDATE student SET name = "5566"
WHERE id IN
<foreach collection="list" item="item" open="(" separator="," close=")">
#{item}
</foreach>
</update>
<update id="batchUpdateStudentWithMap" parameterType="java.util.Map">
UPDATE student SET name = #{name}
WHERE id IN
<foreach collection="idList" item="item" open="(" separator="," close=")">
#{item}
</foreach>
</update>
public void batchUpdateStudentWithMap() {
List<Integer> ids = Arrays.asList(2,3,4,5,6,7);
Map<String, Object> param = new HashMap<>();
param.put("idList", ids);
param.put("name", "mmao789");
try (SqlSession session = sqlSessionFactory.openSession()) {
session.update("mybatisdemo.domain.Student.batchUpdateStudentWithMap", param);
session.commit();
}
}
<delete id="batchDeleteStudent" parameterType="java.util.List">
DELETE FROM student
WHERE id IN
<foreach collection="list" item="item" open="(" separator="," close=")">
#{item}
</foreach>
</delete>
public void batchDeleteStudent() {
List<Integer> ids = new ArrayList<>();
for (int i = 4; i < 8; i++) ids.add(i);
try (SqlSession session = sqlSessionFactory.openSession()) {
session.delete("mybatisdemo.domain.Student.batchDeleteStudent", ids);
session.commit();
}
}
| 屬性 | 說明 | 常用值 |
|---|---|---|
| collection | 要遍歷的集合參數名稱 | list / array / map 的 key |
| item | 每次迭代的元素別名 | item / obj / e |
| index | 索引別名(List/Array 為索引,Map 為 key) | index / idx |
| separator | 元素間分隔符 | , / ; / AND |
| open / close | 整體前後包裹字串 | ( / ) / WHERE |
預設 ExecutorType.SIMPLE 每條 SQL 獨立發送。啟用批次執行器可合併 PreparedStatement:
try (SqlSession session = sqlSessionFactory.openSession(ExecutorType.BATCH)) {
StudentMapper mapper = session.getMapper(StudentMapper.class);
for (Student s : largeList) {
mapper.insert(s); // 內部攜積批次
}
session.commit(); // 一次性提交
}
或在 Mapper 介面方法上標註 @Options(executorType = ExecutorType.BATCH)。
VALUES (...), (...) 多值插入,單條 SQL 上限 max_allowed_packet(預設 4MB)COPY 或 INSERT ... SELECT FROM UNNEST 超大批次VALUES,需用 INSERT ALL ... SELECT * FROM DUAL 或 FORALL (PL/SQL)VALUES (...), (...),1000 筆限制,超過需分批或用 TVPMyBatis 批次操作核心在於 <foreach> 產生符合資料庫方言的批次 SQL,搭配 ExecutorType.BATCH 復用 PreparedStatement,可獲得數十倍寫入效能提升。實務上務必注意單條 SQL 大小限制、主鍵衝突處理、事務邊界與資料庫特定語法差異。