mybatis-plus saveOrUpdate详细解析

mybatis-plus saveOrUpdate详细解析

saveOrUpdate() 方法介绍

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

功能描述: 根据实体对象的主键 ID 进行判断,存在则更新记录,否则插入记录。
返回值: boolean,表示插入或更新操作是否成功。

// TableId 注解属性值存在则更新记录,否插入一条记录
boolean saveOrUpdate(T entity);

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

saveOrUpdate() 源码解析

  1. saveOrUpdate(T entity): 可以看出,是根据id值判断为新数据。如果没有传id值则会 进入save()方法
    @Override
    public boolean saveOrUpdate(T entity) {
        if (null != entity) {
            TableInfo tableInfo = TableInfoHelper.getTableInfo(this.entityClass);
            Assert.notNull(tableInfo, "error: can not execute. because can not find cache of TableInfo for entity!");
            String keyProperty = tableInfo.getKeyProperty();
            Assert.notEmpty(keyProperty, "error: can not execute. because can not find column for id from entity!");
            Object idVal = tableInfo.getPropertyValue(entity, tableInfo.getKeyProperty());
            return StringUtils.checkValNull(idVal) || Objects.isNull(getById((Serializable) idVal)) ? save(entity) : updateById(entity);
        }
        return false;
    }

2.saveOrUpdate(T entity, Wrapper<T> updateWrapper):优先判断能否按照updateWrapper更新,否则继续执行saveOrUpdate(T)方法

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

动手试一下

现有测试数据如下:

在这里插入图片描述

  • 使用saveOrUpdate(T entity)但是不传id,如下:

    {
        "title": "重大新闻",
        "content": "啥事没有",
        "coverImg": "https://111.com",
        "state": "草稿",
        "createUser": 1,
        "createTime": "2024-09-20T13:58:57",
        "updateTime": "2024-09-20T13:58:57",
        "categoryId": 100
    }
    
        @Override
        public void saveOrUpdateArticle(Article article) {
            saveOrUpdate(article, Wrappers.<Article>lambdaUpdate().set(Article::getTitle, "hello"));
        }
    

    在这里插入图片描述
    可以发现,直接新增了数据。由于找不到id,因此认为这是一条新内容

  • 使用saveOrUpdate(T entity, Wrapper<T> updateWrapper),同样不传id

      @Override
        public void saveOrUpdateArticle(Article article) {
            saveOrUpdate(article, Wrappers.<Article>lambdaUpdate().set(Article::getTitle, "hello"));
        }
    

    在这里插入图片描述
    发现确实是优先执行了 updateWrapper,更新了title但是没更新category_id

附(持续更新):

  • saveOrUpdate方法找的id并不是自动找字段id,或者说是主键。而是去找@TableId注解的字段,如果发现错误,不妨先检查以下自己的实体类里面有没有加上。

  • 与单行数据相同,mybatis-plus同样提供了针对批量修改插入数据的方法

    // 批量修改插入
    boolean saveOrUpdateBatch(Collection<T> entityList);
    // 批量修改插入
    boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize);
    
  • 回到saveOrUpdate(T entity, Wrapper<T> updateWrapper)方法

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

    先尝试了update,然后再执行了saveOrUpdate。为什么不直接一步到位,感觉上是多了一步无用的操作。
    大家也不妨思考一下这个逻辑,原因如下:

    • 部分字段更新: 当需要更新实体对象的部分字段,而不是全部字段时,可以使用 updateWrapper 来指定需要更新的字段。例如,只想更新title字段,而不影响其他字段。

    • 条件更新: 当需要根据某些条件来更新记录时,可以使用 updateWrapper 来指定这些条件。例如,只想更新某个用户的文章标题,而不仅仅是根据 id。

    • 确保数据存在: 当需要确保数据存在时,即使更新操作失败,也可以尝试插入新记录。 这种情况下,saveOrUpdate(entity)会在更新失败时插入新记录,确保数据不会丢失。

官方文档:
https://baomidou.com/guides/data-interface/#saveorupdate

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

骑着猪看大海

你的鼓励是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值