MyBatis 批量更新在 Oracle 和 MySQL 中的 XML 寫法不同,關鍵在於 <foreach> 標籤的 open/close 屬性設置,以及 MySQL 需要 JDBC 連接參數支持多語句執行。
Oracle 不支持單條 SQL 多條更新語句,需用 PL/SQL 匿名塊包裹:
<update id="batchUpdate" parameterType="java.util.List">
<foreach collection="list" item="item" index="index"
open="BEGIN " close=" END;" separator=";">
UPDATE test
<set> test = #{item.test} + 1 </set>
WHERE id = #{item.id}
</foreach>
</update>
open="BEGIN "、close=" END;":生成 BEGIN stmt1; stmt2; END; 結構separator=";":語句間用分號分隔#{item.xxx} 參數佔位符防止 SQL 注入MySQL 支持單次執行多條語句,但需開啟連接參數:
<update id="batchUpdate" parameterType="java.util.List">
<foreach collection="list" item="item" index="index"
open="" close="" separator=";">
UPDATE test
<set> test = #{item.test} + 1 </set>
WHERE id = #{item.id}
</foreach>
</update>
jdbc:mysql://192.168.1.236:3306/test?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true
若不添加 allowMultiQueries=true,執行時會拋出「can't execute multiple statements」異常。
public void batchUpdate(List<TestEntity> list) {
sqlSession.update("namespace.batchUpdate", list);
}
// 測試數據構造
List<TestEntity> list = new ArrayList<>();
list.add(new TestEntity(1, 10));
list.add(new TestEntity(2, 20));
batchUpdate(list);
SqlSessionFactory 使用 BATCH 模式可進一步提升性能| 現象 | 原因 | 解決 |
|---|---|---|
| Oracle 報 ORA-00933 | 缺少 BEGIN/END 包裹 | 檢查 foreach open/close 屬性 |
| MySQL 批量無效果 | 未開啟 allowMultiQueries | JDBC URL 添加參數 |
| 參數綁定報錯 | 用 ${} 而非 #{} 導致類型錯誤 | 統一使用 #{} 參數佔位符 |
MyBatis 批量更新核心在於 <foreach> 的正確配置:Oracle 需 PL/SQL 包裹,MySQL 需 JDBC 參數支持。掌握兩者差異,結合批次控制與事務管理,即可高效實現跨數據庫的批量更新需求。