mybatis批量操作
操作数据库(mysql)属于io操作 io是很慢的 sql优化先不谈 那么首先要做的就是减少与数据库建立连接的次数 这时候批量操作就显得尤为重要 主要讲的是 forearch标签
参数
collection
:要迭代的数组或集合的名称。item
:当前迭代的元素的名称。index
:当前迭代的元素在数组或集合中的索引。open
:迭代开始时的 XML 标记。close
:迭代结束时的 XML 标记。separator
:迭代元素之间的分隔符。
查询
这个就是一个非常之常用的啦,也就是mysql里面的in 操作
<select id="batchQuery" resultType="java.util.LinkedHashMap">
select
id ,name,age
where
sex = 0 and id in
<foreach collection="list" item="item" open="(" close=")" separator=",">
#{item}
</foreach>
</select>
插入
批量插入前 需要注意 因为循环迭代 最终的sql可能会变得很长很长 过长时需要通过一些限制的方法
private void batchInsert(List<Map<String, Object>> result) {、
//batchSize 为你限制每次最多可以插入的条数 我是写在配置文件里面了方便调试
if (result.size() != 0) {
System.out.println("数据总量 : " + result.size());
// 计算需要分批插入的次数
int totalBatches = (int) Math.ceil((double) result.size() / batchSize);
// 循环插入每个批次的数据
for (int i = 0; i < totalBatches; i++) {
int fromIndex = i * batchSize;
int toIndex = Math.min((i + 1) * batchSize, result.size());
List<Map<String, Object>> batch = result.subList(fromIndex, toIndex);
// 执行插入操作
dataMapper.batchInsertMap(batch);
System.out.println("插入第 " + (i + 1) + "次 数据量为: " + batch.size() + " 还剩 " + (totalBatches - i - 1) + "次");
}
}
}
<insert id="batchInsert">
INSERT INTO table(name,age,sex)
VALUES
<foreach collection="result" item="list" separator=",">
(#{list.name},#{list.age},#{list.sex})
</foreach>
</insert>
上面针对于批量插入的解决方案 那么问题来了 如果说有些字段 被设置为唯一索引 那么插入的时候会报异常 由于是批量插入 就会导致插入失败(异常前插入的是否成功先不研究,要从源头解决问题),千万不要for循环单条插入并捕获异常...
以下是正确的解决方案(我原来也不会,但是学会了就是自己的!) 选择适合当前业务的
插入冲突做更新
这个操作也就是将原来冲突的进行删除 再添加 用到关键字 REPLACE 也就是替换
<insert id="batchInsert">
REPLACE INTO table(name,age,sex)
VALUES
<foreach collection="result" item="list" separator=",">
(#{list.name},#{list.age},#{list.sex})
</foreach>
</insert>
插入冲突忽略/跳过
这个操作遇到冲突时就会直接跳过此次插入
<insert id="batchInsert">
---mysql数据库不加 or 目前数据库 sqllite
INSERT or IGNOREINTO table(name,age,sex)
VALUES
<foreach collection="result" item="list" separator=",">
(#{list.name},#{list.age},#{list.sex})
</foreach>
</insert>
删除
这个就没什么好赘述的了
<delete id="batchDelete">
delete
from table
WHERE id IN
<foreach collection="idList" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
更新
这个操作之前连接数据库需要加一个参数 &allowMultiQueries=true 这个参数允许在单个连接上执行多个 SQL 查询 因为被分号分隔会视为多条sql 但是他还是有点慢。。建议做成异步的或者 case when 实现真正的批量
并且注意分隔符 是分号!
<update id="batchUpdate" parameterType="java.util.List">
<foreach collection="list" item="item" separator=";">
update table
<set>
name=#{item.name},
age= #{item.age}
</set>
where id = #{item.id}
</foreach>
</update>