我是靠谱客的博主 可耐发箍,这篇文章主要介绍关于Mybatis-plus Lambda自动填充失效和条件为空报错的问题,现在分享给大家,希望可以做个参考。

关于Mybatis-plus Lambda自动填充失效和条件为空报错的问题

    • 使用 LambdaWrapper 更新部分字段,导致自动填充失效
      • 原因
      • 出现范围
      • 解决方案
    • 使用 LamdaWrapper 条件为空,出现执行报 SQL 语法错误
      • 原因
      • 出现范围
      • 解决方案
    • 总结

MyBatis-Plus 提供了自动填充功能,可以选择在新增或更新时自动填充指定字段;同时也提供了 基于 > Lambda 的 Wrapper 构造器使得代码更加精简。

但是,如果使用 LambdaWrapper时会出现以下两个问题:

  1. 使用 LambdaWrapper 更新部分字段,导致自动填充失效

  2. 使用 LamdaWrapper 条件为空,出现执行报 SQL 语法错误

以下,针对两种情况详细说明

使用 LambdaWrapper 更新部分字段,导致自动填充失效

自动字段填充功能,代码如下所示,可以自动在新增操作时,更新创建时间,更新操作时,更新更新时间

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
/** * 记录创建时间 */ @TableField(fill = FieldFill.INSERT) private LocalDateTime createTime; /** * 记录更新时间 */ @TableField(fill = FieldFill.INSERT_UPDATE) private LocalDateTime updateTime;

但是,如果使用 LambdaWrapper 进行部分字段更新,并且不传递实体对象,则无法触发自动填充,导致自动填充失效,代码如下所示

复制代码
1
2
3
4
5
6
// 更新置顶字段 lambdaUpdate().set(topped != null, Voter::getTopped, topped) .eq(Voter::getId, voterId) .update();

原因

由于MyBatis-Plus 字段填充是必须依赖于实体对象,通过实体对象进行自动插入,如果参数中不包含实体对象,则无法触发字段自动填充

上述代码中出现了Voter::getId 但是该参数,只是作为voterId的字段映射使用,并未提供实体

官方解释 Issue 地址:Github Issue 地址

出现范围

MyBatis-Plus 中 update 方法有三种重载,分别是

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 无参, 无法自动填充 default UpdateChainWrapper update() { return ChainWrappers.updateChain(getBaseMapper()); } // wrapper 作为参数,无法自动填充 default boolean update(Wrapper updateWrapper) { return update(null, updateWrapper); } // 包含实体,可以自动填充 default boolean update(T entity, Wrapper updateWrapper) { return SqlHelper.retBool(getBaseMapper().update(entity, updateWrapper)); }

所以,所有 Lambda 表达式执行后使用 update 方法进行部分字段更新时,并没有实体作为参数,都会引起无法触发自动填充

而其他全量更新方法: updateById(T entity)updateById(T entity)updateBatchById(Collection entityList)saveOrUpdate(T entity)都包含了实体,不受影响

解决方案

方案一:

添加实体类作为参数,此时需要考虑更新策略

默认 MyBatis-Plus 更新策略为实体内字段如果为 null 则该字段不进行更新,此时 new Voter()就可以满足;

如果更新策略允许插入 null ,则需要查询出对应实体,再进行更新。

复制代码
1
2
3
4
5
6
7
8
9
10
// 更新置顶字段, 默认更新策略,实体字段为null 不进行更新 lambdaUpdate().set(topped != null, Voter::getTopped, topped) .eq(Voter::getId, voterId) .update(new Voter()); // 更新置顶字段, 更新策略,实体字段null 进行更新 lambdaUpdate().set(topped != null, Voter::getTopped, topped) .eq(Voter::getId, voterId) .update(getById(voterId));

方案二:

使用其他全量更新方法: updateById(T entity)updateById(T entity)updateBatchById(Collection entityList)saveOrUpdate(T entity)进行更新

使用 LamdaWrapper 条件为空,出现执行报 SQL 语法错误

继续使用以上代码, 使用lambdaUpdate或者UpdateWrapper ,不添加实体作为参数, 条件更新,当topped 不为空,则更新 topped 字段。

复制代码
1
2
3
4
5
6
7
// 更新置顶字段, 默认更新策略,实体字段为null 不进行更新 lambdaUpdate().set(topped != null, Voter::getTopped, topped) .eq(Voter::getId, voterId) // 无实体参数 .update();

看似没有问题的代码,实际会在topped 字段为空时,报 SQL 语法错误,错误如下:

复制代码
1
2
3
4
5
6
7
8
9
10
### Error updating database. Cause: java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'WHERE (id = '1')' at line 3 ### The error may exist in com/linkdood/app/mapper/VoterMapper.java (best guess) ### The error may involve com.linkdood.app.mapper.VoterMapper.update-Inline ### The error occurred while setting parameters ### SQL: UPDATE voter WHERE (id = ?) ### Cause: java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'WHERE (id = '1')' at line 3 ; bad SQL grammar []; nested exception is java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'WHERE (id = '1')' at line 3] with root cause

原因

从以上报错信息中可以看出,由于 topped 为空,则拼接的 sql 出现了问题,导致语法错误

出现范围

部分字段更新,且有可能条件为空,例如 PATCH接口 和 POST均可能出现该问题

解决方案

方案一: 添加实体作为参数,同样需要考虑更新策略

复制代码
1
2
3
4
5
6
7
// 更新置顶字段, 默认更新策略,实体字段为null 不进行更新 lambdaUpdate().set(topped != null, Voter::getTopped, topped) .eq(Voter::getId, voterId) // 添加实体参数 .update(new Voter());

方案二: 条件判断放在外面, 如果包含多个条件,条件会比较复杂

复制代码
1
2
3
4
5
6
7
8
9
// 更新置顶字段, 默认更新策略,实体字段为null 不进行更新 if (topped != null) { lambdaUpdate().set(Voter::getTopped, topped) .eq(Voter::getId, voterId) // 无实体参数 .update(); }

方案三:使用其他全量更新方法: updateById(T entity)updateById(T entity)updateBatchById(Collection entityList)saveOrUpdate(T entity)进行更新

总结

该问题,Mybaits-Plus 开发者是知道的,但是因为使用情况没有普适性,均可以使用全量更新方法进行代替,所以没有作为Bug进行修复。

但是实际开发中应该熟悉以上情况的出现场景和解决方案,避免出现误以为MyBatis-Plus 帮我们做了,但是实际他又没做的情况。

---------------------
作者:assember
来源:CSDN
原文:https://blog.csdn.net/assember/article/details/108617148?utm_medium=distribute.pc_aggpage_search_result.none-task-blog-2aggregatepagefirst_rank_ecpm_v1~rank_v31_ecpm-2-108617148.pc_agg_new_rank&utm_term=LambdaUpdateWrapper%E4%B8%BA%E7%A9%BA&spm=1000.2123.3001.4430
版权声明:本文为作者原创文章,转载请附上博文链接!
内容解析By:CSDN,CNBLOG博客文章一键转载插件

最后

以上就是可耐发箍最近收集整理的关于关于Mybatis-plus Lambda自动填充失效和条件为空报错的问题的全部内容,更多相关关于Mybatis-plus内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(71)

评论列表共有 0 条评论

立即
投稿
返回
顶部