起因:
事情是这样的 —— 昨天风和日丽,本想优雅地写完一个更新接口就下班,结果这接口跟我玩起了捉迷藏:调用成功了,SQL 日志也打印了,数据库里的数据却纹丝不动!😤
一、🕵️ 排查过程:一顿操作猛如虎,结果全是二百五
- 首先检查 SQL 日志:完美!生成的 UPDATE 语句完全符合预期,参数也没错
- 接着怀疑数据库事务:查了半天,事务提交正常,没毛病
- 然后猜测是不是数据被逻辑删除了?查了数据库的 is_del 字段,明明是 0(未删除)啊!
- 最后甚至怀疑是缓存问题:清了缓存,重启服务,问题依旧...
就在我快要怀疑人生的时候,突然瞥见实体类上的一行代码:
@TableLogic
private Integer isDel;
抱着 "死马当活马医" 的心态,我注释掉了这个注解,再次调用接口 —— 奇迹发生了!数据更新成功了!🤯
二、🤔 为什么 @TableLogic 会搞事情?
这个注解的本职工作是帮我们自动处理逻辑删除:
- 查询时自动加
WHERE is_del = 0 - 删除时自动变成
UPDATE ... SET is_del = 1
但它有个隐藏特性:更新操作也会自动带上 is_del = 0 的条件!
也就是说,即使你的代码里没写,MyBatis-Plus 也会默默给你生成这样的 SQL:
UPDATE user SET name = '张三' WHERE id = 1 AND is_del = 0
那为什么我的数据 is_del 明明是 0 却更新失败?后来发现是因为我在全局配置里给逻辑删除字段设了默认值,而这个默认值和实体类注解的配置产生了隐秘的冲突... 具体为啥至今没完全搞懂,反正就是抽风了!😅
三、🚧 填坑指南:如何优雅避开这个坑?
如果你也遇到类似问题,这里有几个解决方案:
1、临时方案:直接去掉 @TableLogic 注解
手动在查询条件里加 eq("isDel", 0),虽然麻烦但踏实
2、正确姿势:使用 UpdateWrapper 明确指定条件
UpdateWrapper<User> wrapper = new UpdateWrapper<>();
wrapper.eq("id", userId)
.set("name", newName)
// 明确指定逻辑删除条件,覆盖自动生成的条件
.eq("is_del", 0);
userMapper.update(null, wrapper);
3、终极方案:检查全局配置与注解是否匹配
# 确保全局配置和注解的字段、值都一致
mybatis-plus:
global-config:
db-config:
logic-delete-field: isDel
logic-not-delete-value: 0
logic-delete-value: 1
四、📝 总结一下
@TableLogic 是个好东西,能帮我们省不少事,但它的自动条件拼接有时候会像个 "热心过头的邻居"—— 好心办坏事。
记住这几点能少走弯路:
- 逻辑删除字段的配置要全局统一
- 更新操作遇到诡异问题时,检查一下是不是它在搞鬼
- 复杂场景下,手动控制条件比依赖自动拼接更靠谱
希望我的踩坑经历能帮你避开这个 "隐形炸弹"!如果觉得有用,就点个赞再走吧~👍
4276

被折叠的 条评论
为什么被折叠?



