MyBatisPlus批量操作

标签: 无 分类: 未分类 创建时间:2022-10-29 07:09:27 更新时间:2024-11-23 10:24:24

前言

使用mybatis plus自带的插入语句,有些不给力,如果你定义了自增的id,那么在批量插入的时候,就会出现下面的一些问题,但是如果你去掉了实体类的自增id,虽然可以执行批量插入,但是在执行update方法的时候,因为无法根据主键进行更新,所以更新的时候,就会有问题。最好的办法就是自定义批量插入语句。

1.定义xml

1
2
3
4
5
6
7
8
9
10
<!--批量插入操作-->
<insert id="batchSave" parameterType="java.util.List">
INSERT INTO daily (SiteNo, RecordTime, SumFlux)
VALUES
<foreach collection="list" item="item" index="index" separator=",">
(
#{item.SiteNo},#{item.RecordTime},#{item.SumFlux}
)
</foreach>
</insert>

2.修改mapper

1
2
3
4
5
/**
* 批量插入
* @param dailys
*/
void batchSave(@Param(value = "list")List<Daily> dailys);

3.使用

1
2
List<Daily> subList=new ArrayList();
dailyMapper.batchSave(subList);

问题

1.Error getting generated key or setting result to parameter object
在执行批量插入的时候,虽然可以插入成功,但是报了一个错误:必须执行该语句才能获得结果。如果我的实体类中没有id这个字段,插入的时候是不报错的。也就是说批量插入的操作,这个主键的生成策略还是有影响的。

【解决方法】
(1) 第一种:曲线救国的思想就是在批量插入的时候,不要使用id主键。要么就要自己去拼接insert into 方法。比如下面的更新和插入的例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?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="com.tellme.mapper.UserTMapper">
<insert id="batchSave" parameterType="java.util.List">
insert into user_t (user_name, password,
age)
VALUES
<foreach collection="list" item="item" index="index" separator=",">
(
#{item.userName,jdbcType=VARCHAR},
#{item.password,jdbcType=VARCHAR},
#{item.age,jdbcType=INTEGER}
)
</foreach>
</insert>
<insert id="batchUpdate">
<foreach collection="list" item="item" index="index" open="" close="" separator=";">
UPDATE user_t
SET user_name = #{item.userName}
WHERE id= #{item.id}
</foreach>
</insert>
</mapper>

(2) 第二种:就是在使用jdbc的时候,指定批量操作

1
2
3
4
5
// mysql
jdbc.jdbcUrl=jdbc:mysql://127.0.0.1:3306/databaseName?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true

// sqlserver
datasource.url=jdbc:sqlserver://127.0.0.1:1433;DatabaseName=databaseName;allowMultiQueries=true
参考文章:
1.mybatis批量insert出现Error getting generated key or setting result to parameter object解决办法
2.[2.3.1]sqlserver2008R2 insertBatch 报[必须执行该语句才能获得结果] 这个问题四年前就有了,到现在也没有一个明确的解决方案。里面提到了一个 为什么不用 mp idWroker 完美解决呢?
3.mybatis plus 报错com.microsoft.sqlserver.jdbc.SQLServerException: 必须执行该语句才能获得结果 这里采用的就是报错不予处理的方式解决的问题。因为是主键ID回填,但是要求该数据库提供的 JDBC 驱动可以支持返回批量插入的主键值(JDBC提供了接口,但并不是所有数据库都完美实现了该接口)因此到目前为止,可以完美支持该功能的仅有MySQL数据库。由于SQL Server数据库官方提供的 JDBC 只能返回最后一个插入数据的主键值,所以不能支持该功能。
4.mybatis-plus使用上需要注意的问题 一种是在mysql的数据源中加入allowMultiQueries=true,还有一种结果在sql中使用igrone,我试了一下在其后加上allowMultiQueries=true,发现可以实现。
5.MyBatis-Plus id主键使用ID_WORKER策略踩坑记录 官方说这里默认使用ID_WORKER策略,实际上就是一种id生成策略。
6.mybatis 中 使用 allowMultiQueries=true datasource.url=jdbc:sqlserver://127.0.0.1:1433;DatabaseName=databaseName;allowMultiQueries=true
7.mybatis(6)—实现批量操作allowMultiQueries=true配置 批量插入时,可以构建多个value()。最终与数据库执行时只是一条sql语句。

2.Mapped Statements collection does not contain value for deleteByid
在执行批量删除的时候,报了这个错误。因为我自定义了 mapper.xml 但是里面没有deleteByid的声明,理论上不应该啊,不是兼容的吗?我还需要单独创建一个deleteByid接口吗?

【解决方法】
我就是在xml文件和mapper映射文件中增加了一个 deleteById 方法

1
2
3
<delete id="deleteById" parameterType="int">
delete from hourly where id=#{id}
</delete>

3.传入的请求具有过多的参数。该服务器支持最多 2100 个参数。请减少参数的数目,然后重新发送该请求
在执行批量插入的时候,出现了这个问题,我插入的时候,插入的条数是339条,参数的个数为11个,总共 339*11=3729,超过了2100个数量,需要分批插入。

1
2
3
4
5
6
7
8
9
10
11
<insert id="batchSave" parameterType="java.util.List">
INSERT INTO hourly (SiteNo, RecordTime, SumFlux, SumHeat, [hour], recorddate, Tempe,
Press, Enthalpy, last_sum_flux, last_sum_heat)
VALUES
<foreach collection="list" item="item" index="index" separator=",">
(
#{item.SiteNo},#{item.RecordTime},#{item.SumFlux},#{item.SumHeat},#{item.hour},#{item.recorddate},
#{item.Tempe},#{item.Press},#{item.Enthalpy},#{item.last_sum_flux},#{item.last_sum_heat}
)
</foreach>
</insert>

【解决方法】
参数过多,那就只能分批插入了,11个参数,总共2100,一次只能插入190条。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
* 批量插入
* @param hourlys
*/
public void batchSave(List<Hourly> hourlys){
// 每次需要插入的总量除以90
int count = 190;
// 每次要插入多少条
int batch = hourlys.size() / count;
if (hourlys.size() % count != 0) {
batch = batch + 1;
}

//循环批量保存每组数据
for (int i = 0; i < batch; i++) {
List<Hourly> subList = null;
if (i == batch - 1) {
subList = hourlys.subList(count * i, hourlys.size());
} else {
subList = hourlys.subList(count * i, count * (i + 1));
}
hourlyMapper.batchSave(subList);
}
}
小额赞助
本人提供免费与付费咨询服务,感谢您的支持!赞助请发邮件通知,方便公布您的善意!
**光 3.01 元
Sun 3.00 元
bibichuan 3.00 元
微信公众号
广告位
诚心邀请广大金主爸爸洽谈合作
每日一省
isNaN 和 Number.isNaN 函数的区别?

1.函数 isNaN 接收参数后,会尝试将这个参数转换为数值,任何不能被转换为数值的的值都会返回 true,因此非数字值传入也会返回 true ,会影响 NaN 的判断。

2.函数 Number.isNaN 会首先判断传入参数是否为数字,如果是数字再继续判断是否为 NaN ,不会进行数据类型的转换,这种方法对于 NaN 的判断更为准确。

每日二省
为什么0.1+0.2 ! == 0.3,如何让其相等?

一个直接的解决方法就是设置一个误差范围,通常称为“机器精度”。对JavaScript来说,这个值通常为2-52,在ES6中,提供了Number.EPSILON属性,而它的值就是2-52,只要判断0.1+0.2-0.3是否小于Number.EPSILON,如果小于,就可以判断为0.1+0.2 ===0.3。

每日三省
== 操作符的强制类型转换规则?

1.首先会判断两者类型是否**相同,**相同的话就比较两者的大小。

2.类型不相同的话,就会进行类型转换。

3.会先判断是否在对比 null 和 undefined,是的话就会返回 true。

4.判断两者类型是否为 string 和 number,是的话就会将字符串转换为 number。

5.判断其中一方是否为 boolean,是的话就会把 boolean 转为 number 再进行判断。

6.判断其中一方是否为 object 且另一方为 string、number 或者 symbol,是的话就会把 object 转为原始类型再进行判断。

每日英语
Happiness is time precipitation, smile is the lonely sad.
幸福是年华的沉淀,微笑是寂寞的悲伤。