源码分析Mybatis拦截器(Interceptor)拦截saveBatch()获取不到实体id的原因

1.背景

由于业务需求想在Mybatis拦截器层面获取insert后实体id去做相关业务。但是发现执行saveBatch()方法时,获取参数实体的时候,拿不到自增id。但是save()方法可以。

save方法之所以可以是因为:

MybatisPlus的BaseMapper执行insert方法后实体带自增id的原因是,在数据库表中设置了主键自增属性。当插入一条新的记录时,数据库会自动为这条记录生成一个唯一的自增id,并将这个id赋值给实体类中的主键属性。因此,当你查询这条记录时,实体类中的主键属性就会带有自增id。

save()和saveBatch()的基本原理:

MybatisPlus是MyBatis的增强工具,它在MyBatis的基础上只做增强不做改变,为简化开发、提高效率而生。在具体操作上,MybatisPlus提供了save()和saveBatch()两种方法用于数据的保存。

save()方法是通过调用BaseMapper封装的单条保存数据的insert()方法实现的。也就是说,当我们调用save()方法时,会直接将数据插入到数据库中。

而saveBatch()方法则是用于批量插入数据。在使用时,需要传入一个列表集合以及一个默认的批量插入数量(默认为1000)。在内部实现上,MybatisPlus会遍历这个列表集合,并依次将数据插入到数据库中。此外,需要注意的是,虽然saveBatch()方法可以实现批量插入,但根据实际测试和观察,批量插入的效率可能会受到一定影响。因此,在使用saveBatch()方法进行批量插入时,可能需要考虑优化方案以提高插入效率。

拦截器代码(简化版):


@Intercepts({@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})})
public class TodoInterceptor implements Interceptor {@Overridepublic Object intercept(Invocation invocation) throws Throwable {Object[] args = invocation.getArgs();Object parameter = args[1];// 调用原始方法Object result = invocation.proceed();if (parameter instanceof Enquiry) {Enquiry enquiry = (Enquiry) parameter;}return result;}

2.现象

我分别执行save和saveBatch方法,附带截图:

save():

saveBatch():

如图所示,saveBatch()方法的实体在拦截器里是获取不到自增id的。特别说明下,debug你会发现,MybatisPlus执行saveBatch()方法会遍历这个列表集合,并依次将数据插入到数据库中。因为拦截器会执行次数是和实体列表的数量是一致。

3.源码分析原因

第一步:

ServiceImpl类

    public boolean saveBatch(Collection<T> entityList, int batchSize) {String sqlStatement = this.getSqlStatement(SqlMethod.INSERT_ONE);return this.executeBatch(entityList, batchSize, (sqlSession, entity) -> {//这里是拼装SQL,即每个实体类都是一个insert into 的sqlsqlSession.insert(sqlStatement, entity);});}

第二步:

SqlHelper类
public static <E> boolean executeBatch(Class<?> entityClass, Log log, Collection<E> list, int batchSize, BiConsumer<SqlSession, E> consumer) {Assert.isFalse(batchSize < 1, "batchSize must not be less than one", new Object[0]);return !CollectionUtils.isEmpty(list) && executeBatch(entityClass, log, (sqlSession) -> {int size = list.size();int idxLimit = Math.min(batchSize, size);int i = 1;//从这里for可以看出,每实体就是一个insert语句for(Iterator var7 = list.iterator(); var7.hasNext(); ++i) {E element = var7.next();//这里就是与数据库配置,执行了sql,同时拦截器也是在这个方法里面执行的consumer.accept(sqlSession, element);if (i == idxLimit) {//这里很重要,刷新缓存,执行这里后可以拿到插入后的id。//所以,大家想想,上面accept方法拿不到id的原因就是如此了。sqlSession.flushStatements();idxLimit = Math.min(idxLimit + batchSize, size);}}});}

展示debug结果:

大家可以看到,执行了sqlSession.flushStatements()方法后就出现了id。所以也是大家发现在controller层,service层等执行saveBatch方法能拿到id,在拦截器却不可以,原因就在这里

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/195854.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于单片机16路抢答器仿真系统

**单片机设计介绍&#xff0c; 基于单片机16路抢答器仿真系统 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机的16路抢答器仿真系统是一种用于模拟和实现抢答竞赛的系统。该系统由硬件和软件两部分组成。 硬件方面&am…

配置iTerm2打开自动执行命令

打开iTerm2&#xff0c;commado&#xff0c;打开profies->edit profies&#xff0c;点击号&#xff0c;创建一个新的profile 在新的profile中填写 name&#xff1a;随意 command&#xff1a;Login Shell Send text at start&#xff1a;执行脚本的命令&#xff0c;不想写路…

Linux虚拟机中网络连接的三种方式

Linux 虚拟机中网络连接的三种方式 先假设一个场景&#xff0c;在教室中有三个人&#xff1a;张三、李四和王五&#xff08;这三个人每人有一台主机&#xff09;&#xff0c;他们三个同处于一个网段中&#xff08;192.169.0.XX&#xff09;&#xff0c;也就是说他们三个之间可…

CSS的选择器(一篇文章齐全)

目录 Day26&#xff1a;CSS的选择器 1、CSS的引入方式 2、CSS的选择器 2.1 基本选择器​编辑 2.2 组合选择器 2.3 属性选择器 2.4 伪类选择器 2.5 样式继承 2.6 选择器优先级 3、CSS的属性操作 3.1 文本属性 3.2 背景属性 3.3 边框属性 3.4 列表属性 3.5 dispal…

中间件安全:Apache 目录穿透.(CVE-2021-41773)

中间件安全&#xff1a;Apache 目录穿透.&#xff08;CVE-2021-41773&#xff09; Apache 的 2.4.49、2.4.50 版本 对路径规范化所做的更改中存在一个路径穿越漏洞&#xff0c;攻击者可利用该漏洞读取到Web目录外的其他文件&#xff0c;如系统配置文件、网站源码等&#xff0c…

在 Linux 上搭建 Java Web 项目环境(最简单的进行搭建)

要在 Linux 上安装的程序有 1.JDK (要想运行 java 程序 JDK 是必不可少的) 2.Tomcat &#xff08;HTTP 服务器&#xff0c;是管理 Web 项目的常用工具&#xff09; 3. mysql &#xff08;数据库&#xff09; 一.安装 JDK 博主使用的 Linux 发行版是 centos &#xff0c;cen…

NLP学习:深入NLP

个人博客:Sekyoro的博客小屋 个人网站:Proanimer的个人网站 之前学过一段时间NLP,因为其中涉及到一些深度学习常用的知识或者框架,但苦于不系统以及没有任务focus不能长久.这里借助微软的教程写点东西. tokenization&&representation 将一句话中的单词分割就是分词(…

盼望许久的百度熊终于收到了

文|洪生鹏 我怀着激动的心情&#xff0c;终于收到了百度熊礼品。 在我想象中&#xff0c;这只熊应该很大&#xff0c;能够填满我的怀抱。 但当我打开礼盒的那一刻&#xff0c;我有些惊讶。 它居然这么小&#xff0c;与我预期的相差甚远。 不过&#xff0c;当我们仔细一看&#…

SQL基础理论篇(七):多表关联的连接算法

文章目录 简介Nested LoopsMerge JoinHash Join总结参考文献 简介 多表之间基础的关联算法一共有三种&#xff1a; Hash JoinNested LoopsMerge Join 还有很多基于这三种基础算法的变体&#xff0c;以Nested Loops为例&#xff0c;就有用于in和exist的半连接&#xff08;Nes…

【算法】树形DP③ 监控二叉树 ⭐(二叉树染色二叉树灯饰)!

文章目录 前期知识 & 相关链接例题968. 监控二叉树解法1——标记状态贪心解法2——动态规划 相关练习题目P2458 [SDOI2006] 保安站岗⭐&#xff08;有多个儿子节点&#xff09;&#x1f6b9;LCP 34. 二叉树染色⭐&#xff08;每个节点 单独dp[k 1]数组&#xff09;LCP 64.…

【论文阅读】MAG:一种用于航天器遥测数据中有效异常检测的新方法

文章目录 摘要1 引言2 问题描述3 拟议框架4 所提出方法的细节A.数据预处理B.变量相关分析C.MAG模型D.异常分数 5 实验A.数据集和性能指标B.实验设置与平台C.结果和比较 6 结论 摘要 异常检测是保证航天器稳定性的关键。在航天器运行过程中&#xff0c;传感器和控制器产生大量周…

蓝桥杯单片机综合练习——工厂灯光控制

一、题目 二、代码 #include <reg52.h>sfr AUXR 0x8e; //定义辅助寄存器sbit S5 P3^2; //定义S5按键引脚 sbit S4 P3^3; //定义S4按键引脚unsigned char led_stat 0xff; //定义LED当前状态 unsigned char count 0; //定义50ms定时中断累…