MybatisPlus 使用 saveOrUpdate() 方法踩坑记录(慎用)

【Exception】MybatisPlusException: can not find lambda cache for this entity Caused by: com.baomidou.mybatisplus.core.exceptions.MybatisPlusException: can not find lambda cache for this entity [fun.maso.entity.SubTableBaseEntity] 阅读详情

点击上方“芋道源码”,选择“设为星标”

管她前浪,还是后浪?

能浪的浪,才是好浪!

每天 10:33 更新文章,每天掉亿点点头发...

源码精品专栏

 

来源:blog.youkuaiyun.com/weixin_45369440/

article/details/116044771

b40481e9e9e0d76fb3b0ab0f0a06b2fc.jpeg


今天的想法是,要在插入数据库时,如果有某某一个主要字段的值重复,则不插入,否则则插入!看了一下mybatis-Plus是有这个saveOrUpdate 方法!

原本使用save时是没有问题了,改成saveOrUpdate 用了一下就报错了。

com.baomidou.mybatisplus.core.exceptions.MybatisPlusException: error: can not execute. because can not find column for id from entity!

就是这个mybatisPlus不能找到哪个是主键字段,因为这个saveOrUpdate默认是根据主键执行操作的!

所有需要在原本的实体类的主键头上,打个@TableId,如下,后面是对应数据库的字段,已经主键自动递增。

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Subject {

  @TableId(value = "subject_Code", type = IdType.AUTO)
  private long subjectCode;

  private String subjectNameCn;

  private String subjectNameEn;

  private String subjectHref;

  private long subjectParentCode;

  private long levelCode;

  private int isDelete;

  private long operateTimestamp;


}

不过还有个问题,就是这个是根据主键做操作的,但是我主键本来就是自动递增肯定不会有问题的,接下来就是想个办法,让他根据指定字段做操作,好像是有提供了一个口子。

// 根据updateWrapper尝试更新,否继续执行saveOrUpdate(T)方法
boolean saveOrUpdate(T entity, Wrapper<T> updateWrapper);

我再去看一下怎么操作的!

研究尝试了半天,终于搞出来了,可能是很少有人会像我这样做吧!所以我自己尝试了下。

当saveOrUpdate不使用条件构造器时,会先做根据主键查询,如果查出来的结果为0,那么就执行插入操作,如果查出来的结果不为0,则执行更新操作。

但是一般情况下,主键都不会重复啊!所有我就用条件构造器Wrapper!

UpdateWrapper<Subject> subject_name_cn = new UpdateWrapper<Subject>()
   .eq("subject_Name_Cn", subjectNameCn);
subjectService.saveOrUpdate(subject,subject_name_cn );

这样改变后的结果就是会先执行修改,如果执行一条,则执行成功,如果执行结果为0,再执行根据主键查询,然后做插入操作!

其实有点多此一举的感觉,因为既然都已经更新不到结果了,那么肯定是没有这个字段咯!

不过转念一想,你是指定字段没有,又不是主键没有!

但是主键自增那肯定没有啊!

所有我又想到一个骚操作,我不传UpdateWrapper而传QueryWrapper会怎么样呢!

会不会加在查询条件种呢!我丢进去没有报错,有点小激动,不知道结果如何!

QueryWrapper<Subject> subject_name_cn1 = new QueryWrapper<Subject>()
                    .eq("subject_Name_Cn", subjectNameCn);
subjectService.saveOrUpdate(subject,subject_name_cn1);

好吧!上来全给我Update了!丝毫不留情面!我把数据删了再试试!

好吧!然并卵!幻想破灭!跟传UpdateWrapper没有区别!~告辞!

看了一下源码,默认参数是Wrapper类型,然后根据条件构造器更新,成功则返回,不成功则走无条件构造器的方法。

default boolean saveOrUpdate(T entity, Wrapper<T> updateWrapper) {
    return this.update(entity, updateWrapper) || this.saveOrUpdate(entity);
}

我感觉应该加个类型判断!

if(updateWrapper instanceof QueryWrapper){
  //去拼接查询语句!
 }
  if(updateWrapper instanceof UpdateWrapper){
  //去拼接更新语句!
 }

这样就不会只根据ID来死查了!

为什么要用updateWrapper?

它与queryWrapper的区别就是:updateWrapper用set来设置修改的数据;queryWrapper应用select来设置要查出来的数据。

saveOrUpdate 是否有映射id

我们知道mybatis在插入时,会映射id,但是如果是saveOrUpdate会怎么样呢?

比如我saveOrUpdate()后,需要用他的id,但是我传进去的对象是没有id的。

@Test
 void saveOrUpdate(){
       UserText userText = new UserText();
       userText.setUserSex(Sex.MAN);
       boolean b = userTextService.saveOrUpdate(userText);
       System.out.println(userText.getUserId());
   }

可以看到他先通过id查了没有再进行插入,然后返回新的id。

==>  Preparing: SELECT user_id,user_name,user_sex,start_time FROM user_text WHERE user_id=?
==> Parameters: 0(Long)
<==      Total: 0
Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6d0fe80c]
Fetched SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6d0fe80c] from current transaction
==>  Preparing: INSERT INTO user_text ( user_sex ) VALUES ( ? )
==> Parameters: 1(Integer)
<==    Updates: 1

不过这个update,不用试我都感觉难搞,因为你如果没有id,那么你传入这个对象的值,可能查出多个对象,那么他要把哪个id映射回来,是吧!

@Test
void saveOrUpdate(){
     UserText userText = new UserText();
     userText.setUserSex(Sex.MAN);
     UpdateWrapper<UserText> objectUpdateWrapper = new UpdateWrapper<UserText>()
             .eq("user_sex",Sex.MAN);
     boolean b = userTextService.saveOrUpdate(userText,objectUpdateWrapper);
     System.out.println(userText.getUserId());
 }

但还是试一下,当我们加了一个UpdateWrapper后,有执行成功,执行了3条,返回了id为0。

但是这次加了wrapper,我再试试如果只插入一条,会怎么样。哈哈,不去读源码去debug,就只能这样试试了,莫怪。

诶,对啊,我去看看源码先,看能不能看出什么门道。

之前好像也有看了点源码。两种不同构造的方法,执行的逻辑也不一样。

boolean saveOrUpdate(T entity); 

default boolean saveOrUpdate(T entity, Wrapper<T> updateWrapper) {
 return this.update(entity, updateWrapper) || this.saveOrUpdate(entity);
}

区别不大,就是会多执行一步更新,如果执行成功就直接走,执行不成功再根据这个对象做saveOrUpdate。

进去翻了翻就是,如果通过id查到值,就根据id更新,不然就做新增。

所以也就不用试了,还是自己手写一个吧,如果需要返回id的话。

慎用!

细思极恐,当你是主键自动生成的数据,一定要写UpdateWrapper,不然你必然是一直插入!完全不会更新,因为默认是用id查询的。

而主键生成的数据,一般都不会去写一个id,所以啊!赶快看看吧!

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://gitee.com/zhijiantianya/ruoyi-vue-pro

  • 视频教程:https://doc.iocoder.cn/video/

UpdateWrapper 小贴士

上面虽然写了updateWrapper可以写一个set属性,有两种情况。

首先,我们一个对象,有5条属性,只有4条有值,1条没有值。

mybatis-plus在执行时,会先去看看你的对象哪条属性有值,哪条没有。

只会更新有值的属性,所以只会更新4个属性,另外一个属性并不会把他置空。

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://gitee.com/zhijiantianya/yudao-cloud

  • 视频教程:https://doc.iocoder.cn/video/

后续

我发现一个很垃圾的,前面我吹的那个updateWrapper的set多牛逼,其实是我想的太美了,他只是在原本的基础上再加一个字段!我吐了!

UpdateWrapper<GameScorePo> updateWrapper = new UpdateWrapper<GameScorePo>()
                   .eq("game_id",gameScorePo.getGameId())
                   .eq("team_id",gameScorePo.getTeamId())
                   .eq("quarter",gameScorePo.getQuarter())
                   .set("score",gameScorePo.getScore());

           gameScoreService.saveOrUpdate(gameScorePo,updateWrapper);

这样的执行结果是这样的!

fe457dbfc9c8a215cee8984f50629a63.png

两个score,我吐了!

难道是我打开的姿势不对?

查了一下知道这个set怎么样了

f22717c18b85278fbba8766f308c96f4.png

就是不要丢对象,丢一个空的对象,这样就能set了!

单独的set好用,但是用在saveOrUpdate就不好用咯!看自己的需求走吧!



欢迎加入我的知识星球,一起探讨架构,交流源码。加入方式,长按下方二维码噢:

d26454d1f174ba4fa0595168584a392e.png

已在知识星球更新源码解析如下:

b6f4a780fb9a21a2845bfb09a895903e.jpeg

74b2107b206bacfb6b82cc1ed94db48e.jpeg

0226e38c2e04ecb0ba6ca5e50c0032cf.jpeg

78442edc4e94758b00fe0ca878c991c9.jpeg

最近更新《芋道 SpringBoot 2.X 入门》系列,已经 101 余篇,覆盖了 MyBatis、Redis、MongoDB、ES、分库分表、读写分离、SpringMVC、Webflux、权限、WebSocket、Dubbo、RabbitMQ、RocketMQ、Kafka、性能测试等等内容。

提供近 3W 行代码的 SpringBoot 示例,以及超 4W 行代码的电商微服务项目。

获取方式:点“在看”,关注公众号并回复 666 领取,更多内容陆续奉上。

文章有帮助的话,在看,转发吧。
谢谢支持哟 (*^__^*)
MybatisPlus 使用 saveOrUpdate 详解(如果有某某一个主要字段的值重复,则更新,否则插入!) 阅读详情

相关推荐

MybatisPlus saveOrUpdate 实战避坑指南:从主键困惑到条件构造器的正确姿势

本文深入解析MybatisPlus的saveOrUpdate方法在实际项目中的使用技巧与常见陷阱。从主键标注、自增主键处理到条件构造器的正确使用,详细介绍了如何避免数据重复插入和更新失败的问题。特别针对MySQL的ON DUPLICATE KEY UPDATE语法进行了性能优化分析,并提供了多字段唯一约束和批量操作的最佳实践方案。

weixin_30892889的博客 576

Mybatis-Plus批量插入导致的主键冲突问题

mybatis-plus批量插入踩坑

qq_39974348的博客 1万+

MybatisPlus批量saveOrUpdate优化技巧:用LambdaQueryWrapper实现按业务字段更新

本文深入探讨了MybatisPlus框架中saveOrUpdate方法的局限性,并提供了基于LambdaQueryWrapper的优化方案。针对依赖业务字段而非主键进行更新的场景,文章通过库存设备同步的实战案例,详细讲解了如何利用saveOrUpdate(T entity, Wrapper<T> updateWrapper)方法实现高效、灵活的批量“存在即更新,否则插入”操作,有效提升了数据处理性能与代码可维护性。

sony5的博客 846

使用LambdaQueryWrapper 报错MybatisPlusException: can not find lambda cache for this property [****]

单元测试 Mockito 报使用LambdaQueryWrapper 报错MybatisPlusException: can not find lambda cache for this property [****] 异常问题

RichardGeek的博客 7423

慎用,Mybatis-Plus可能导致死锁

线上Mybatis-Plus引发的死锁场景分析

咖啡攻城狮的博客 3713

oracle ebs form 10g安装教程

这个窗口需要想想,你要安装的类型,不要盲目点击“下一步”,因为一旦Oracle安装后,重新安装之前,需要卸载Oracle干净才能重新安装,有时还会出现错误。到了该窗口后,需要耐心等待安装,安装到一大半后,自动弹出一个窗口,让我们选择Oracle安装第2部分磁盘的路径,继续安装,然后坐等安装结束。自定义安装Oracle根目录,点击“下一步”按钮后,耐心等待几秒钟,工具自动加载产品列表,加载完后,自动跳转到“选择安装类型”窗口。注:等待几秒钟后,关闭dos窗口,不必惊慌,自动调转到安装界面。

XIELIUHAI001的博客 475

MybatisPlus 使用 saveOrUpdate() 方法踩坑记录

今天的想法是,要在插入数据库时,如果有某某一个主要字段的值重复,则不插入,否则则插入!看了一下mybatis-Plus是有这个saveOrUpdate 方法!原本使用save时是没有问题了,改成saveOrUpdate 用了一下就报错了。com.baomidou.mybatisplus.core.exceptions.MybatisPlusException: error: can not exe...

Java精选 1102

西门子S7-200 SMART与施耐德ATV变频器Modbus通讯实战:从接线到稳定运行的完整指南

本文详细介绍了西门子S7-200 SMART PLC与施耐德ATV变频器之间实现稳定Modbus通讯的完整实战指南。内容涵盖从硬件接线、参数配置、PLC程序编写到触摸屏设计的全流程,并分享了提升通讯稳定性的关键技巧和常见故障排查方法,助力工业自动化系统可靠运行。

kkk56的博客 1108

Mybatisplus中saveOrUpdate()方法并发问题

Mybatisplus中saveOrUpdate()方法并发问题

2302_79802185的博客 1504

鸿蒙系统下基于WebRTC的高效音视频通话开发实战

本文详细介绍了在鸿蒙系统下集成WebRTC技术实现高效音视频通话的实战开发。通过分析鸿蒙分布式软总线与WebRTC低延迟特性的结合优势,提供了从环境搭建、NAPI桥接层开发到音视频采集、P2P连接建立与渲染的完整流程。文章重点探讨了如何利用鸿蒙特性进行性能优化,包括网络自适应、抗抖动策略及系统级调优,旨在帮助开发者构建稳定、低延迟的实时通信应用。

night的博客 572

VirtualBox增强功能安装全指南:从下载到配置复制粘贴功能

本文详细介绍了VirtualBox增强功能的完整安装与配置流程,重点解决了虚拟机与主机间复制粘贴、文件拖放等核心协作难题。通过分步指南和故障排查,帮助用户在不同操作系统(如Windows、Linux)中实现无缝集成,提升虚拟化工作效率与体验。

weixin_29206669的博客 419

MybatisPlus 使用 saveOrUpdate 详解(慎用),及问题解决方法&mysql保存或更新 ON DUPLICATE KEY UPDATE

今天的想法是,要在插入数据库时,如果有某某一个主要字段的值重复,则不插入,否则则插入!看了一下mybatis-Plus是有这个saveOrUpdate 方法!原本使用save时是没有问题了,改成saveOrUpdate 用了一下就报错了。就是这个mybatisPlus不能找到哪个是主键字段,因为这个saveOrUpdate默认是根据主键执行操作的!所有需要在原本的实体类的主键头上,打个@TableId,如下,后面是对应数据库的字段,已经主键自动递增。

qq_43842093的博客 3万+

STM32单片机远程升级

stm32远程升级

fang_yang_wa的博客 1万+

MybatisPlus的saveOrUpdate方法实战:如何避免‘找不到主键字段‘的坑?

本文深入解析MybatisPlus的saveOrUpdate方法在实战中抛出'找不到主键字段'异常的根源与解决方案。核心在于必须为实体类正确配置@TableId注解,明确主键字段和IdType策略。文章通过库存设备关联的实战案例,演示了如何结合LambdaQueryWrapper实现基于业务唯一键的'存在则更新,不存在则插入'逻辑,并提供了高并发场景下的注意事项与性能优化建议。

metal的博客 944

工业组态软件Intouch(单机版)入门{第一篇}

通俗来讲Intouch就是一个能将PLC里的信号显示在画面上的软件。

weixin_41571357的博客 1万+

AI原生应用API编排:如何实现高效的权限管理?

随着GPT-4、Claude 3等大模型的普及,AI原生应用(从设计之初就以AI为核心的应用)正从“概念”走向“落地”。依赖大量外部API的协同工作(如用户身份API→大模型生成API→支付API→存储API)。但随之而来的挑战是:如何在复杂的API调用链中,确保每个环节的权限合规?本文将聚焦这一问题,覆盖API编排的基础逻辑、权限管理的核心机制(如RBAC/ABAC)、实战工具链(如OPA策略引擎),以及常见场景的解决方案。本文将按照“场景引入→核心概念→原理拆解→实战演练→趋势展望”的逻辑展开。

大数据洞察的博客 452

mybatis-plus saveOrUpdate详细解析

- 插入新记录:当对象的所有字段都为新值且对象的主键字段未设置或设置为默认值时,saveOrUpdate将执行插入操作。 - 更新现有记录:如果对象的主键字段设置了有效的值,并且该值对应于数据库中现有的记录,那么saveOrUpdate将执行更新操作。

骑着猪看大海的博客 6973

YOLO26改进 - 注意力机制 | ParNet并行子网络:多分支协同优化特征表达,增强模型判别能

本文介绍了ParNet注意力机制及其在YOLO26中的应用。ParNet注意力通过并行子网络结构,将网络层组织成多个子网络并行处理输入特征,降低了传统注意力机制在处理长序列时的计算复杂度。该机制采用VGG风格的块和特征融合策略,具有低深度高性能、参数效率高、可扩展性强和并行化能力好等创新点。我们将ParNet注意力引入YOLO26,在检测头部分应用该机制。通过实验训练改进后的模型,有望提升YOLO26在目标检测任务中的性能。

魔改工程师的博客 443

mybatis-plus save update saveorupdate相关问题

MyBatis-Plus 提供了一个 saveOrUpdate(T entity) 方法,该方法会根据提供的实体对象的状态决定执行保存还是更新操作。为了更好地理解和使用此方法,我们需要了解 MyBatis-Plus 是如何判断是否执行更新操作的。saveOrUpdate 方法内部会检查传入的实体对象是否已经在数据库中存在。如果实体对象的主键字段已经存在于数据库中,则执行更新操作;否则,执行插入操作。

qq_41392518的博客 4508

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

Mybatis一级缓存和mybatisplus 踩坑记

事故描述 某商品的照片分两种类型:A商品外观照片 和 B商品配件照片两个相册 ,它们保存在同一张picture表中。 在一个事务内按照片类型批量更新商品照片,但操作人只有保存A类型照片的权限,因需要将该商品A照片清空,然后插入新A类照片,然后取商品所有照片,仅发现B类照片,未发现新插入的A类照片。 事务的隔离性 start transaction; ## 插入id=1数据 INSERT ...

qq_31826151的博客 7010

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

MybatisPlus saveOrUpdate进阶指南:自定义主键与非主键更新策略

本文深入探讨MybatisPlus的saveOrUpdate方法,解析其默认依赖主键的局限性,并提供基于自定义字段的灵活更新策略。通过TableId注解配置、Wrapper条件包装器及批量处理优化等技巧,帮助开发者实现高效数据持久化,特别适合需要非主键更新的复杂业务场景。

quiet的专栏 605

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

MybatisPlus中saveOrUpdate的实战应用:如何优雅处理主键冲突与数据更新

本文深入探讨MybatisPlus中saveOrUpdate方法的实战应用,解析如何优雅处理主键冲突与数据更新。通过@TableId注解配置主键策略,结合LambdaQueryWrapper实现自定义条件判断,并分享批量操作、乐观锁处理等进阶技巧,帮助开发者提升数据库操作效率与代码质量。

weixin_29292431的博客 378
上一篇: 国庆假期,整整七天,我用76张图把Spring AOP给画明白了!
下一篇: Spring Boot+Netty+Websocket实现后台向前端推送信息
公众号-芋道源码
博客等级 码龄10年 1634粉丝 377原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值