Ich habe die SQL-Protokollierung aktiviert und die Abfrageausgabe untersucht. Für den obigen Fall war es dies:
/* 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=?
Der notwendige Join ist also bereits enthalten und sieht aus wie alles, was benötigt würde, ist dies:
@Where(clause = "ppg_status <> 'D'")
Es stellt sich jedoch heraus, dass dies nicht der Fall ist funktionieren, da Hibernate den falschen Tabellenaliasnamen voranstellt:
where
(
purchasepr0_.ppg_status <> 'D'
)
and purchasepr0_.crd_id=?
Sobald einer Tabelle ein Alias zugewiesen wurde, ist es leider nicht möglich, den ursprünglichen Tabellennamen zu verwenden - also purchase_product_group.ppg_status <> 'D'
würde nicht funktionieren. Und mir ist keine Möglichkeit bekannt, den von Hibernate verwendeten Aliasnamen programmgesteuert zu bestimmen - daher scheint die Wahl derzeit entweder darin zu bestehen, den von Hibernate verwendeten Aliasnamen fest zu codieren (dh purchasepr1_.ppg_status <> 'D'
) oder um den exists
zu verwenden in der Frage beschriebene Methode.
AKTUALISIERUNG: Bei weiteren Nachforschungen stellt sich heraus, dass die Hardcodierung der Aliasnamen nicht immer praktikabel ist. Hier ist eine Kriterienabfrage, bei der dies nicht funktionieren würde:
/* 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=?
Am Ende habe ich den @Where
aufgegeben Ansatz und verwendet @Filter
Stattdessen scheint dies viel besser zu sein, da es HQL anstelle von Datenbankfeldnamen akzeptieren kann und sich bei Anwendung auf Entitätsebene auf Beziehungen auswirkt (im Gegensatz zu @Where
).