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

Hibernate关联@Filter、@JoinTable与JOINED继承时抛缺失FROM子句异常

解决方案

方法一:将过滤器定义在父类实体上(推荐)

把软删除过滤器直接定义在父类AbstractInvoiceParty上,Hibernate会自动处理继承结构下的表关联和过滤逻辑,避免表别名引用顺序错误:

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@FilterDef(name = "filterDeleted") // 定义过滤器
@Filter(name = "filterDeleted", condition = "deleted_at IS NULL") // 过滤条件
public abstract class AbstractInvoiceParty {
    
    protected Date deletedAt = null;

}

同时移除OwnerGroup中多对多关联上的@Filter注解:

@Entity
public class OwnerGroup {

    @ManyToMany(mappedBy = "ownerGroups")
    // 移除此处的@Filter注解
    protected Set<OwnerGroupsInvoiceParty> partyOnInvoices = new HashSet<>();

    public Set<OwnerGroupsInvoiceParty> getPartyOnInvoices() {
       return this.partyOnInvoices;
    }
}

激活过滤器的代码保持不变:

session.enableFilter("filterDeleted");

效果说明

修改后Hibernate生成的SQL会正确关联父表并应用过滤条件,示例如下:

SELECT partyoninv0_.owner_groups_id  as owner_gr2_267_0_,
       partyoninv0_.party_on_invoices_id as party_on1_267_0_,
       ownergroup1_.id                   as id2_21_1_,
       ownergroup1_1_.deleted_at         as deleted_3_21_1_ 
FROM 
   owner_groups_invoice_party_owner_groups partyoninv0_ 
INNER JOIN 
   owner_groups_invoice_party ownergroup1_ 
     ON partyoninv0_.party_on_invoices_id = ownergroup1_.id 
LEFT OUTER JOIN 
   abstract_invoice_party ownergroup1_1_ 
     ON ownergroup1_.id = ownergroup1_1_.id 
WHERE 
   partyoninv0_.owner_groups_id=?
   AND ownergroup1_1_.deleted_at IS NULL

方法二:调整多对多关联上的过滤器条件(备选)

如果必须在多对多关联上定义过滤器,可以通过子查询方式绕过表别名顺序问题:

@Entity
public class OwnerGroup {

    @ManyToMany(mappedBy = "ownerGroups")
    @Filter(name = "filterDeleted", condition = "{s}.id IN (SELECT id FROM abstract_invoice_party WHERE deleted_at IS NULL)", 
            aliases = {
                @org.hibernate.annotations.SqlFragmentAlias(alias = "s", table = "owner_groups_invoice_party") 
            })
    protected Set<OwnerGroupsInvoiceParty> partyOnInvoices = new HashSet<>();

    public Set<OwnerGroupsInvoiceParty> getPartyOnInvoices() {
       return this.partyOnInvoices;
    }
}

这种方式通过子查询直接检查父表的软删除状态,不需要依赖父表的JOIN顺序,但可读性和性能不如方法一。


问题根源

原代码中过滤器定义在多对多关联上时,Hibernate错误地将过滤条件放在了子类表的INNER JOIN ON子句中,但父表是之后才通过LEFT OUTER JOIN关联的,导致SQL中引用了尚未出现的表别名ownergroup1_1_,触发PostgreSQL的语法错误。将过滤器移到父类后,Hibernate会正确处理继承结构的查询逻辑,确保过滤条件在父表关联后再应用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 03:45:38