【问题标题】:How to add a where clause to a Hibernate @OneToMany explicit join table entity?如何将 where 子句添加到 Hibernate @OneToMany 显式连接表实体?
【发布时间】:2017-12-07 10:25:34
【问题描述】:

给定两个实体:

  • Card
  • PurchaseProductGroup,它有一个ppg_status 列(在实体上名为status 的字段)可以是'A'(活动)或'D'(已删除)

它们在概念上具有多对多关系,但使用了一个明确定义的名为 PurchaseProductGroupCard 的连接表实体(因此可以为每个映射分配一个外部 ID)。所以CardPurchaseProductGroup 都有@OneToManyPurchaseProductGroupCard 的关系,例如在Card 中有以下内容:

@OneToMany(mappedBy = "card")
private Set<PurchaseProductGroupCard> purchaseProductGroups;

这需要加以限制,以便排除状态为'D' 的purchaseProductGroups。一种似乎可行的方法是将@Where 注释放在@OneToMany 下方:

@Where(clause = "exists (select * from purchase_product_group ppg
                         where ppg.ppg_id = ppg_id AND ppg.ppg_status <> 'D')")

...但是有没有更好的方法来做到这一点?理想情况下,希望 Hibernate 加入表并有一个像 "purchaseProduct.status &lt;&gt; 'D'") 这样的子句。

【问题讨论】:

    标签: oracle hibernate many-to-many jointable hibernate-filters


    【解决方案1】:

    我打开了 SQL 日志记录并检查了查询输出。对于上述情况,它是这样的:

    /* load one-to-many com.prepaytec.pacasso.common.model.Card.purchaseProductGroups */
    select
        * /* the actual field list has been omitted for brevity */
    from
        pacasso.purchaseprodgrp_card purchasepr0_
    inner join
        pacasso.purchase_product_group purchasepr1_
            on purchasepr0_.ppg_id=purchasepr1_.ppg_id
    where
        (
            exists (
                select
                    *
                from
                    purchase_product_group ppg
                where
                    ppg.ppg_id = purchasepr0_.ppg_id
                    AND ppg.ppg_status <> 'D'
            )
        )
        and purchasepr0_.crd_id=?
    

    所以已经包含了必要的连接,它看起来就像所有需要的是这样的:

    @Where(clause = "ppg_status <> 'D'")
    

    然而,事实证明 不起作用,因为 Hibernate 预先添加了错误的表别名:

    where
        (
            purchasepr0_.ppg_status <> 'D'
        )
        and purchasepr0_.crd_id=?
    

    不幸的是,一旦为表分配了别名,就无法使用原始表名 - 所以purchase_product_group.ppg_status &lt;&gt; 'D' 将不起作用。而且我不知道以编程方式确定 Hibernate 使用的别名的方法 - 所以目前的选择似乎是硬编码 Hibernate 使用的别名(即purchasepr1_.ppg_status &lt;&gt; 'D')或使用问题中描述的exists 方法。

    更新:进一步调查发现硬编码别名并不总是可行的。这是一个不起作用的条件查询:

    /* criteria query */
    select
        * /* the actual field list has been omitted for brevity */
    from
        pacasso.merchant_acquirer this_ 
    left outer join
        pacasso.purchaseprod_merchant_acquirer purchasepr2_ 
            on this_.mac_id=purchasepr2_.mac_id 
            and (
                // This wouldn't work with any alias since the required
                // table is pacasso.purchase_product purchasepr3_, which
                // is joined below.
                purchasepr2_.ppr_status <> 'D' 
            )  
    left outer join
        pacasso.purchase_product purchasepr3_ 
            on purchasepr2_.ppr_id=purchasepr3_.ppr_id 
    where
        this_.mac_code=? 
        and this_.cst_id=?
    

    最后我放弃了@Where 方法并改用@Filter,这似乎要好得多,因为它可以接受HQL 而不是数据库字段名称,并且在实体级别应用时会影响关系(不像@Where) .

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-04
      • 2014-01-19
      相关资源
      最近更新 更多