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
相关产品推荐
相关产品推荐

