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 <> 'D'
うまくいきません。そして、Hibernate が使用するエイリアス名をプログラムで判別する方法を私は知りません。そのため、現時点では、Hibernate が使用していることが判明したエイリアス名をハードコードする (つまりpurchasepr1_.ppg_status <> '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
とは異なります)。 ).