mybatis-plus saveOrUpdate详细解析
saveOrUpdate() 方法介绍
- 插入新记录:当对象的所有字段都为新值且对象的主键字段未设置或设置为默认值时,saveOrUpdate将执行插入操作。
- 更新现有记录:如果对象的主键字段设置了有效的值,并且该值对应于数据库中现有的记录,那么saveOrUpdate将执行更新操作。
功能描述: 根据实体对象的主键 ID 进行判断,存在则更新记录,否则插入记录。
返回值: boolean,表示插入或更新操作是否成功。
// TableId 注解属性值存在则更新记录,否插入一条记录
boolean saveOrUpdate(T entity);
// 根据updateWrapper尝试更新,否继续执行saveOrUpdate(T)方法
boolean saveOrUpdate(T entity, Wrapper<T> updateWrapper);
saveOrUpdate() 源码解析
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