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

Hibernate 6.3中@Where和@Loader注解的非弃用替代方案咨询

Hibernate 6.3+ 非弃用软删除实现方案

针对Hibernate 6.3起org.hibernate.annotations.Where和Loader被弃用的情况,替代原@NamedQuery+@SQLDelete的软删除方案有以下几种,均为官方推荐的非弃用方式:

1. 最简方案:使用Hibernate @SoftDelete注解

Hibernate 6.2及以上版本引入了@SoftDelete注解,直接封装了软删除的核心逻辑,无需手动编写删除SQL和过滤规则:

@Entity
// 配置软删除字段、已删除/未删除对应的值
@SoftDelete(
    columnName = "is_deleted",
    deletedValue = "true",
    notDeletedValue = "false"
)
public class Product {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    // 软删除字段,会被@SoftDelete自动维护
    private Boolean isDeleted;
    
    // 其他业务字段...
}
  • 执行删除:调用entityManager.remove(product)时,Hibernate自动执行UPDATE product SET is_deleted = true WHERE id = ?,而非物理删除;
  • 查询过滤:所有JPQL/Criteria查询会自动过滤掉is_deleted = true的记录,无需额外编写条件。

2. 灵活控制方案:@SQLDelete + Hibernate @Filter & @FilterDefinition

如果需要动态控制是否过滤已删除数据,或者兼容部分旧逻辑,可以保留@SQLDelete,用@Filter替代原@Where注解:

第一步:实体类配置

// 定义过滤器参数和规则
@FilterDef(
    name = "excludeDeleted",
    parameters = @ParamDef(name = "deletedStatus", type = Boolean.class)
)
// 绑定过滤器到实体,指定过滤条件
@Filter(
    name = "excludeDeleted",
    condition = "is_deleted = :deletedStatus"
)
@Entity
// 自定义删除SQL,替换为更新软删除字段
@SQLDelete(sql = "UPDATE product SET is_deleted = true WHERE id = ?")
public class Product {
    @Id
    private Long id;
    private Boolean isDeleted = false;
    
    // 其他业务字段...
}

第二步:启用过滤器

在需要过滤已删除数据的会话中启用过滤器:

// 获取Hibernate Session
Session session = entityManager.unwrap(Session.class);
// 启用过滤器并设置参数(只查询未删除数据)
session.enableFilter("excludeDeleted")
       .setParameter("deletedStatus", false);
  • 优势:可根据业务场景动态开关过滤器(比如管理员需要查看已删除数据时,将参数设为true即可)。

3. 复杂逻辑方案:自定义实体监听器

如果软删除时需要额外处理其他业务逻辑(比如更新删除时间、同步关联表状态),可以用JPA生命周期注解实现:

第一步:定义软删除接口(统一规范,可选)

public interface SoftDeletable {
    void setDeleted(boolean deleted);
    void setDeletedAt(LocalDateTime deletedAt);
}

第二步:实现实体监听器

public class SoftDeleteListener {
    @PreRemove
    public void handleSoftDelete(Object entity) {
        if (entity instanceof SoftDeletable) {
            SoftDeletable deletable = (SoftDeletable) entity;
            // 设置软删除标记和删除时间
            deletable.setDeleted(true);
            deletable.setDeletedAt(LocalDateTime.now());
            // 将删除操作转为更新操作
            EntityManager em = PersistenceUtil.getEntityManager();
            em.merge(deletable);
            // 抛出异常阻止物理删除(Hibernate会捕获并执行更新)
            throw new RuntimeException("Soft delete triggered, physical deletion prevented");
        }
    }
}

第三步:绑定到实体类

@Entity
@EntityListeners(SoftDeleteListener.class)
public class Product implements SoftDeletable {
    @Id
    private Long id;
    private Boolean isDeleted = false;
    private LocalDateTime deletedAt;
    
    // 实现接口方法
    @Override
    public void setDeleted(boolean deleted) {
        this.isDeleted = deleted;
    }
    
    @Override
    public void setDeletedAt(LocalDateTime deletedAt) {
        this.deletedAt = deletedAt;
    }
}
  • 查询时:需要在JPQL/Criteria查询中手动添加WHERE isDeleted = false条件,或者用@NamedQuery定义带过滤的查询(原@NamedQuery仍可正常使用)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 23:45:26