前言
1.为什么要使用TableLogic?
(1) 在某些业务需求场景下,删除数据需要采用逻辑删除而不是物理删除
(2) 方便以后数据审计、历史数据的分析、保证多表数据的完整性
然而,这一功能在某些情况下会导致更新操作失效。本文将详细讨论 @TableLogic 如何影响更新操作,并提供相应的解决方案。
开始
@TableLogic 是 MyBatis-Plus 提供的一种注解,用于标记逻辑删除字段。逻辑删除即在数据库中保留数据,只是通过修改特定字段(如 is_delete)的值来标记记录为已删除状态。
.....如何发现这个问题的?
....一天,产品经理突然宣布要将物理删除改成逻辑删除。我对屎山进行了大刀阔斧的改造,自信满满地认为一切都很顺利。
再一段时间后,在天气晴朗的日子中,我发现删除掉一条用户数据后,再进行添加该数据,发现不管添加几次,数据库中就是看不到新的记录。
“这一定是个小问题,”我心想。于是,我信心满满地开始排查 BUG,认为这不过是分分钟的事情。然而,时间一秒一秒地过去……
10分钟,没找到问题;
30分钟,依然没头绪;
1小时,依旧毫无进展。
................
................
直到我注意到了我实体类上的 is_delete 字段上多了个 @TableLogic 注解。
不对劲,很有可能问题出现在这里,我去查阅了各种资料。
果然,问题就是出现在这里。
原来是我同事将 is_delete 这个字段加入了 @TableLogic 注解,导致了更新操作不生效,所以在进行新增数据时始终无法添加。
问题解决了!
@TableName("syg.syg_believer")
@Data
public class Believer implements Serializable {
private Long userId;
private String openId;
private String level;
.........
// @TableLogic(delval = "1")
private Integer isDelete;
}
在这个示例中,isDelete 字段被标记为逻辑删除字段。@TableLogic 注解告诉 MyBatis-Plus 在执行删除操作时,将该字段的值设置为 1 而不是物理删除记录。
由于is_delete 这个字段加入了 @TableLogic 注解,所以我在更新用户数据的时候,这个注解导致了updateById这个方法失效了,所以怎么添加数据都不会成功。
//信众存在并且处于删除状态
if (Objects.nonNull(believer) && believer.getIsDelete()==BELIEVER_DELETED){
believer.setIsDelete(BELIEVER_NOT_DELETED);
BeanUtils.copyProperties(addBelieverPO, believer);
believer.setMerit(addBelieverPO.getMerit());
believer.setRegTime(new Date());
believer.setOpenId(String.valueOf(DEFAULT_OPENID));
believer.setAge(age.getYears());
believer.setUserId(sysUser.getUserId());
//判断信众等级
LevelEnums level = LevelEnums.getLevel(believer.getGrowth(), believer.getMerit());
believer.setLevel(String.valueOf(level));
if (!updateById(believer)){
return AjaxResult.error(BELIEVER_ADD_ERROR);
}
}
@TableLogic 是 MyBatis-Plus 提供的一种注解,用于标记逻辑删除字段。逻辑删除即在数据库中保留数据,只是通过修改特定字段(如 is_delete)的值来标记记录为已删除状态。
更新操作为何失效
使用 @TableLogic 注解后,当我们尝试更新记录时,MyBatis-Plus 会自动将逻辑删除字段加入 where 子句,以确保只操作未被逻辑删除的记录。如果记录已经被逻辑删除(如 is_delete = 1),那么更新操作将不会匹配到任何记录,从而导致更新不生效。如在这个示例中执行UpdateById的操作,对其他字段的设置忽略,只关心is_delete这个字段
UPDATE syg_believer
SET age = #{age} (其它字段忽略....) WHERE id = #{userId} AND is_delete = 0;
UPDATE syg_believer SET age = #{age} (其它字段忽略....) WHERE id = #{userId} AND is_delete = 0;
如果 user_id 的记录 is_delete 为 1,则此更新操作不会生效。
解决方案
方案 1:通过 UpdateWrapper 手动指定更新逻辑删除字段
UpdateWrapper<Believer> updateWrapper = new UpdateWrapper<>();
updateWrapper
.set("is_delete", 1)
.eq("user_id", userId);
userMapper.update(null, updateWrapper);
方案 2:自定义 SQL 更新
<update id="believerUpdateByUserId">
UPDATE syg_believer SET is_delete = #{isDelete} WHERE user_id = #{userId}
</update>
结语
通过理解和使用 MyBatis-Plus 提供的 @TableLogic 注解,我们可以有效地实现逻辑删除,同时避免由于逻辑删除字段导致的更新操作失效问题。
为了避免类似的问题再次发生,建议大家在遇到更新操作不生效的情况时,除了排查常规原因外,也要注意检查是否有类似 @TableLogic 的注解影响了操作逻辑。这个小知识点可以帮助大家扩大排查范围,减少排查时间,提高工作效率。
标签:逻辑,删除,update,believer,TableLogic,注解,失效,delete From: https://blog.csdn.net/weixin_69329906/article/details/140689415