鉴于两个实体:
-
Card
-
PurchaseProductGroup
,其中包含ppg_status
列(实体上名为status
的字段),可以'A'
(活动)或'D'
(已删除)
这些概念上具有多对多关系,但使用了明确定义的名为 PurchaseProductGroupCard
的连接表实体(因此可以为每个映射分配外部ID) . 所以 Card
和 PurchaseProductGroup
与 PurchaseProductGroupCard
的关系都是 @OneToMany
,例如在 Card
中有以下内容:
@OneToMany(mappedBy = "card")
private Set<PurchaseProductGroupCard> purchaseProductGroups;
需要对此进行限制,以便排除状态为 'D'
的purchaseProductGroups . 似乎有效的一种方法是在 @OneToMany
下方放置 @Where
注释:
@Where(clause = "exists (select * from purchase_product_group ppg
where ppg.ppg_id = ppg_id AND ppg.ppg_status <> 'D')")
......但是有更好的方法吗?理想情况下,希望Hibernate加入表并有一个像 "purchaseProduct.status <> 'D'")
这样的子句 .
1 回答
我打开了SQL日志记录并检查了查询输出 . 对于上述情况,这是:
因此,必要的连接已经包含在内,看起来所有需要的是:
但是,事实证明 doesn't 作为Hibernate工作的前缀是错误的表别名:
不幸的是,一旦将一个别名分配给一个表,就不可能使用原始的表名 - 所以
purchase_product_group.ppg_status <> 'D'
并不知道如何通过编程方式确定Hibernate使用的别名 - 所以目前选择似乎是要么硬编码Hibernate使用的别名(即purchasepr1_.ppg_status <> 'D'
),要么使用问题中描述的exists
方法 .UPDATE: 在进一步的调查中发现,对别名进行硬编码是不可行的:
最后我放弃了
@Where
方法并使用了@Filter
,这看起来好多了,因为它可以接受HQL而不是数据库字段名称,并且在实体级别应用时会影响关系(与@Where
不同) .