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

Spring Boot 3升级后Hibernate @Where软删除引发JPA关联查询问题

解决Spring Boot3升级后@Where注解导致关联查询左连接失效的问题

这个问题我升级Spring Boot3时也踩过坑!本质是Spring Boot3搭配的Hibernate 6.x调整了@Where注解的行为:在Hibernate 5.x(Spring Boot2默认版本)中,实体上的@Where条件会被嵌入到关联查询的JOIN子句中;但Hibernate 6.x默认会把这些条件移到WHERE子句,这就破坏了左连接的预期效果——当Group下所有User都被软删除时,WHERE子句的过滤条件会直接排除掉这个Group,而不是返回一个空的users集合。

下面给你两种可行的解决办法:

方案一:全局恢复Hibernate 5.x的@Where行为(最简单)

只需要在你的Spring Boot配置文件中添加一个Hibernate属性,强制让@Where条件回到JOIN子句:

application.properties

spring.jpa.properties.hibernate.where.interpretation=JOIN

application.yml

spring:
  jpa:
    properties:
      hibernate:
        where:
          interpretation: JOIN

配置完成后,重新查询仅包含已删除User的Group,Hibernate生成的SQL就会把User的软删除条件放到LEFT JOIN的ON子句里,和你期望的SQL结构一致,此时就能正确返回带空users集合的Group实体了。

方案二:使用Filter+FilterJoinTable(更灵活,适合多场景)

如果你不想全局修改@Where的行为,或者需要针对不同关联设置不同的过滤规则,可以用Hibernate的过滤器机制:

  1. 为User实体定义过滤器
@Entity(name = "User")
@FilterDef(name = "activeUser", parameters = [ParamDef(name = "isDeleted", type = Boolean::class)])
@Filter(name = "activeUser", condition = "not is_deleted or is_deleted is null")
@SQLDelete(sql = "UPDATE user SET is_deleted = true, updated_at = NOW() WHERE id=?")
class UserEntity(
    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "group_id", nullable = true)
    val group: GroupEntity,
    @OneToOne(cascade = [CascadeType.ALL], mappedBy = "user", fetch = FetchType.EAGER)
    var token: TokenEntity?
)
  1. 在Group的users关联上应用过滤器到JOIN子句
@Entity(name = "Group")
@Where(clause = "not is_deleted or is_deleted is null")
@SQLDelete(sql = "UPDATE group SET is_deleted = true, updated_at = NOW() WHERE id=?")
class GroupEntity(
    @OneToMany(mappedBy = "group", cascade = [CascadeType.ALL], fetch = FetchType.EAGER)
    @FilterJoinTable(name = "activeUser") // 关键:将过滤器应用到JOIN子句
    val users: MutableSet<UserEntity> = HashSet()
)
  1. 全局启用过滤器
    在配置文件中添加属性,让这个过滤器默认开启:
spring.jpa.properties.hibernate.default_filter.activeUser=true

这种方式可以精准控制哪些关联需要应用软删除过滤,同时不影响其他@Where注解的默认行为。

验证方法

开启Hibernate SQL日志后,检查生成的SQL语句,确认User的软删除条件已经出现在LEFT JOIN的ON子句中,而不是WHERE子句,就说明配置生效了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 16:25:16