You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用@SQLDelete实现软删除时如何同步更新modified_by和modified_date字段

问题根因

你遇到的问题本质是@SQLDelete注解的执行逻辑导致的:该注解会直接指定Hibernate执行删除操作时调用的原生SQL,执行过程会跳过实体的生命周期回调(包括你写的@PreRemove方法),也不会同步你在内存中修改的实体属性到数据库,所以审计字段不会更新。
另外先提醒你一个逻辑疏漏:你当前@SQLDelete写的是UPDATE user SET deleted = 0 WHERE user_id = ?,而你配置的@Where(clause="deleted = 0")是过滤掉已删除的记录,这个逻辑是反过来的——删除操作应该把deleted设为非0值才会被过滤,否则相当于执行删除后数据还是会被查询到。


解决方案(优先推荐第二种)

方案1:修改@SQLDelete语句补充字段

如果要继续使用@SQLDelete,直接把审计字段更新逻辑写到SQL里即可:

// 注意deleted要改成1,modifiedDate用数据库当前时间,modifiedBy按实际参数顺序调整即可
@SQLDelete(sql="UPDATE user SET deleted = 1, modified_date = NOW(), modified_by = ?1 WHERE user_id = ?2")

这个方案的缺点是需要手动处理参数顺序,不同实体的表名、字段名不一样的话每个都要单独写,复用性差。

方案2:自定义软删除逻辑(推荐)

放弃@SQLDelete,手动实现删除逻辑,既能触发JPA自动审计,也更灵活好维护:

  1. 先去掉实体上的@SQLDelete注解(@Where注解可以保留,用于自动过滤已删除数据)
  2. 修改Service层的删除逻辑,先查询出实体再更新软删除标记后保存:
// UserServiceImpl.java
@Override
public void deleteUser(Long userId) {
    User user = userRepository.findById(userId)
            .orElseThrow(() -> new IllegalArgumentException("目标用户不存在"));
    // 标记为已删除,注意和你@Where的逻辑对应
    user.setDeleted(1L);
    // 如果你已经开启了@EnableJpaAuditing,modifiedBy、modifiedDate会自动填充,不需要手动set
    userRepository.save(user);
}

如果还没有开JPA审计,在启动类加上@EnableJpaAuditing注解即可,配合你已经加的@LastModifiedDate、@LastModifiedBy注解,每次更新实体时审计字段会自动赋值。


内容的提问来源于stack exchange,提问作者Dio

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 18:54:03