解决MybatisPlus批量插入数据报错:Error getting generated key or setting result to parameter object问题
作者:Duktig丶
问题描述
执行的核心代码:
objectUserService.saveBatch(objectUserList);
在使用MybatisPlus进行执行批量插入操作的时候报错,导致每次插入数据失败。
具体报错信息如下:
xiaoyun_notice- 2020-07-14 20:34:09 [http-nio-9001-exec-1] INFO c.x.api.controller.ObjectController - 【新增通知:step02-object_user批量新增,维护中间表】: userId: 2
xiaoyun_notice- 2020-07-14 20:34:09 [http-nio-9001-exec-1] INFO jdbc.sqltiming - batching 3 statements: 1: INSERT INTO object_user ( obj_id, user_id ) VALUES ( 151, 1 ) 2:
INSERT INTO object_user ( obj_id, user_id ) VALUES ( 151, 2 ) 3: INSERT INTO object_user (
obj_id, user_id ) VALUES ( 151, 3 ) ;
{executed in 75 msec}
xiaoyun_notice- 2020-07-14 20:34:09 [http-nio-9001-exec-1] INFO jdbc.sqltiming - getGeneratedKeys on query: INSERT INTO object_user ( obj_id, user_id ) VALUES ( 151, 3 ) ;
{executed in 0 msec}
xiaoyun_notice- 2020-07-14 20:34:09 [http-nio-9001-exec-1] ERROR c.x.e.handler.GlobalExceptionHandler - nested exception is org.apache.ibatis.executor.ExecutorException: Error getting generated key or setting result to parameter object. Cause: java.lang.NullPointerException
org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.executor.ExecutorException: Error getting generated key or setting result to parameter object. Cause: java.lang.NullPointerException
主要报错信息:
ERROR c.x.e.handler.GlobalExceptionHandler - nested exception is org.apache.ibatis.executor.ExecutorException: Error getting generated key or setting result to parameter object. Cause: java.lang.NullPointerException
问题分析
根据上述的主要报错信息,可以推测出MybatisPlus在底层执行新增操作时,返回的主键为空,报了个空指针的异常,又因为加了事务的缘故,所以每次执行新增操作,失败。
问题解决过程
百度上所说的大多数的解决策略都是说主键生成策略的问题。
即设置mybatis的insert语句useGeneratedKeys属性为false即可解决问题。
网上大多使用的xml去配置,可以在写到SpringBoot的时候,基本就不怎么写xml文件,多以就想着使用注解去设置,还真有设置这样的注解。
@Options(useGeneratedKeys=true,keyProperty="id",keyColumn="id")
option注解标签useGeneratedKeys=true表示使用数据库自动增长的主键,keyColumn用于指定数据库table中的主键,keyProperty用于指定传入对象的成员变量。
Springboot中 Mybatis 配置文件 Mapper参数useGeneratedKeys=“true” keyProperty=“id”,useGeneratedKeys设置为 true 时,表示如果插入的表id以自增列为主键,则允许 JDBC 支持自动生成主键,并可将自动生成的主键id返回。
useGeneratedKeys参数只针对 insert 语句生效,默认为 false;
默认为false怎么还会生效?难道说是MybatisPlus底层有做了处理。
局限性
虽然这样使用可能可以成功,但是批量插入的方法,是MybatisPlus底层提供的,我们没有办法在mapper中添加这个注解,将这个注解添加到当前方法,还是失败。
后续更新
经过各种尝试,这样的方法还是失败,所以这个需求暂时不使用MybatisPlus的批量新增来写了,就自己写个新增的mapper方法吧。
替代解决方案
因为项目开发需要,不能再耗时间,所以干脆就在写个自定义的mapper批量新增的方法来解决这个问题吧。
方法如下:
/** * description: 新增通知时,维护中间表,批量新增 * * @param objId 通知id * @param userIds 用户id集合 * @return 执行条数 */ @Insert({ "<script>", "INSERT INTO object_user(obj_id, user_id,created_at,updated_at) values ", "<foreach collection='userIds' item='item' index='index' separator=','>", "(#{objId}, #{item},now(),now())", "</foreach>", "</script>" }) int saveObjectUserList ( int objId, List<Integer> userIds );
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。