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

这篇具有很好参考价值的文章主要介绍了MybatisPlus 使用 saveOrUpdate 详解(慎用),及问题解决方法&mysql保存或更新 ON DUPLICATE KEY UPDATE。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

今天的想法是,要在插入数据库时,如果有某某一个主要字段的值重复,则不插入,否则则插入!
看了一下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,所以啊!赶快看看吧!


UpdateWrapper 小贴士

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

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

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

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

如果你只想改一条属性,也可以多写一个set,不过感觉没啥必要,不过比较灵活的就是。
你想写另外一个值,就可以写进set里。


2021-05-21 13:31:32

我发现一个很垃圾的,前面我吹的那个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);

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

mybatisplus 保存或者更新,MyBatis-Plus,数据库,MySQL,MybatisPlus,saveOrUpdate,保存或更新
两个score,我吐了!

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

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

mybatisplus 保存或者更新,MyBatis-Plus,数据库,MySQL,MybatisPlus,saveOrUpdate,保存或更新
就是不要丢对象,丢一个空的对象,这样就能set了!

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




INSERT INTO pms_statistic (
	id,
	tenantId,
	tenantName,
	isDeleted,
	createTime
)
VALUES
	(
		6257,50,'保存或修改0',1,'2020-01-00'
	) ,(
		6258,51,'保存或修改1',1,'2020-01-01'
	) ,(
		6259,52,'保存或修改2',1,'2020-01-02'
	) ,(
		62510,53,'保存或修改3',1,'2020-01-03'
	) 
ON DUPLICATE KEY UPDATE tenantId = VALUES(tenantId),tenantName = VALUES(tenantName)
		,isDeleted = VALUES(isDeleted),createTime = VALUES(createTime);

该语句是基于主键(PRIMARY KEY)或唯一索引(UNIQUE INDEX)使用的。
如果已存在该唯一标示或主键就更新(显示受影响行的值:2)

如果不存在该唯一标示或主键则作为新行插入(显示受影响行的值:1)

如上:如果id(6257,6258,6259,62510)存在,根据id更新ON DUPLICATE KEY UPDATE后的字段数据(tenantId = VALUES(tenantId),tenantName = VALUES(tenantName),isDeleted = VALUES(isDeleted),createTime = VALUES(createTime))

执行sql前(存在6257id,其他id不存在)

执行后

6257修改,6258,6259,62510插入

受影响行:5(插入3条,修改1条(修改是两行))

注意:ON DUPLICATE KEY UPDATE只是MySQL的特有语法,并不是SQL标准语法!文章来源地址https://www.toymoban.com/news/detail-679308.html

到了这里,关于MybatisPlus 使用 saveOrUpdate 详解(慎用),及问题解决方法&mysql保存或更新 ON DUPLICATE KEY UPDATE的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • MyBatisPlus解决逻辑删除与唯一索引的兼容问题

    比如有张用户表,在插入或者更新数据的时候,我们需要 用户名称 (username),不能重复。 我们首先考虑的是给该字段创建唯一索引 似乎这样就可以了,然而事情并没有那么简单。 因为我们表中的数据在删除的时候不会真的的删除,而是采用逻辑删除,会有一个 deleted 字段使用

    2023年04月13日
    浏览(69)
  • C语言移除元素问题解决方法详解

    本文详细介绍了解决移除元素问题的三种方法:暴力求解、空间换时间和双指针方法,帮助读者更好地理解和解决类似问题。

    2023年04月24日
    浏览(37)
  • MybatisPlus 超好用的idea代码生成插件,及使用详解

    文章目录 前言 一、MybatisPlus简介 二、MybatisPlus 代码生成插件 1.插件安装与配置 2.生成代码结构、内容展示 3.表新增字段,重新生成实体类覆盖  总结 新需求来了,又添加了好几张表,总不能手写或者复制之前的代码,再一通修改吧?! 一张表需要添加好几个新字段,往实体

    2024年01月24日
    浏览(41)
  • MybatisPlus之QueryWrapper有无条件方法的使用说明

    QueryWrapper 两种重载方法,其中一种是布尔类型condition条件参数,另一种是没有布尔类型参数,比如下面这两个方法: 它们有什么区别呢? 鄙人细研究了一番,得出如下结论: boolean condition:用于指定当前这个条件是否有效;如果为 true,则使用当前条件;如果为 false,则忽

    2024年02月12日
    浏览(40)
  • 解决‘getBaseMapper()‘ in ‘com.baomidou.mybatisplus.extension.service.impl.ServiceImpl‘ clashes with问题

    原因:包的问题 将 import com.baomidou.mybatisplus.mapper.BaseMapper; 改为 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 即可

    2024年02月16日
    浏览(47)
  • 关于MyBatisPlus框架下出现xml里面定义的方法无法被正确识别以及提示调用mysql存储过程时参数无效的问题

    网上很多解决方法都是查看函数名是否一致、命名空间等,但还有一种可能是你调用接口的模块本身的resource文件夹下就有一个含有xml的mapper文件夹,而这个文件夹里面不含有方法A的sql实现,如下图: 导致程序只在这个mapper里面找A的sql实现,那肯定会提示没有找到。 除了检

    2024年02月09日
    浏览(50)
  • 【CAD卡顿解决方法详解,网上最实用五种方法,开机卡顿,拖图卡顿,画直线卡顿等问题,一一详细教你解决】

    我们刚装好CAD时,往往会遇到启动缓慢,画直线卡顿等现象,接下来我就详细介绍如何处理这些问题 面对启动卡顿,我们可以将” 初始化界面 “给关闭掉,在命令行中输入 StartMode 命令,将值设置为 0 设置完成后的启动画面如下 画直线卡顿,往往是因为动态输入没有关闭,

    2024年02月16日
    浏览(45)
  • MybatisPlus使用Left Join...on...一对多多表联查和Ipage分页返回数据问题

    问题: 一对多关系表使用MybatisPlus的Ipage进行分页查询,会先执行联表查询sql语句,然后进行分页。  像图中联表查询一对多关系,会有多条重复数据,使用Ipage分页会将这10条数据返回到xml中resultMap绑定的type。造成一页展示的数据少于10条。 针对这种我们采用子查询的方式解

    2024年02月13日
    浏览(40)
  • AprilTag的使用、相关问题及解决方法

    安装标定功能包 下载棋盘格 http://wiki.ros.org/camera_calibration/Tutorials/MonocularCalibration?action=AttachFiledo=viewtarget=check-108.pdf 启动摄像头 开始标定 参数说明: size:    棋盘内交叉点的个数,行*列 square:  一个格子的边长,单位是m image:  订阅摄像头发布的图像话题(RO

    2024年02月10日
    浏览(36)
  • Hive使用中常见的问题及解决方法

            Hive是基于Hadoop的一个数据仓库工具,可以将结构化的数据文件映射为一张表,并提供SQL查询功能。在工作中大部分场景都会用到,下面列出几个 hive 使用中常见的问题及解决方法。 1)Hive 默认的输入格式处理是CombineHiveInputFormat,会对小文件进行合并 hive (default

    2024年02月10日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包