MyBatis-Plus 更新逻辑删除字段(is_delete)无效问题分析与解决方案
问题背景
在使用 MyBatis-Plus 进行数据更新时,发现 is_delete
字段无法被正确更新,即使显式赋值后,数据库仍然没有变化。以下是两个具体问题和解决方案的总结。
问题1:为什么设置了 is_delete
字段的值但是不更新?
代码示例
ApiKey apiKey = apiKeyRepository.selectOne(queryWrapper);
if (apiKey == null) {return false;
}
// 尝试软删除
apiKey.setIsDelete(1); // 设置为已删除
apiKey.setStatus(ApiKey.STATUS_DISABLED);
int updated = apiKeyRepository.updateById(apiKey); // 执行更新
UPDATE api_key
SET user_id=?, api_key_hash=?, key_name=?, ..., update_time=?
WHERE id=? AND is_delete=0
发现 is_delete
并未出现在 SET
部分,而是作为 WHERE
条件。
原因分析
@TableLogic
的作用:该注解标记的字段(如
is_delete
)会被 MyBatis-Plus 视为逻辑删除字段。updateById()
默认会忽略逻辑删除字段的更新,防止误操作导致数据不一致。同时,MyBatis-Plus 会自动在 SQL 的
WHERE
条件中添加AND is_delete=0
,确保只更新未删除的记录。
设计逻辑:
逻辑删除字段通常由专门的
deleteById()
方法自动处理,而不是手动更新。
问题2:为什么移除了 @TableLogic
注解,is_delete
仍然无法更新?
我怀疑是直接配在了nacos中,然后打印出来发现是值isDelete,导致的全局都是软删除
@Value("${mybatis-plus.global-config.db-config.logic-delete-field}")private String maxApiKeyCount;
最终推荐方案
// 使用 UpdateWrapper 确保更新
apiKeyRepository.update(new UpdateWrapper<ApiKey>().eq("id", apiKey.getId()).set("is_delete", 1).set("status", ApiKey.STATUS_DISABLED)
);
总结
问题 | 原因 | 解决方案 |
---|---|---|
@TableLogic 导致 is_delete 不更新 | MyBatis-Plus 自动忽略逻辑删除字段 | 使用 UpdateWrapper 或 deleteById() |
移除 @TableLogic 后仍然不更新 | 全局配置、字段限制、空值问题 | 检查配置、确保非空、手动更新 |
最佳实践:
逻辑删除 → 直接使用
deleteById()
。手动更新逻辑删除字段 → 使用
UpdateWrapper
。