Jeg slog SQL-logning til og undersøgte forespørgselsoutputtet. For ovenstående tilfælde var det dette:
/* 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=?
Så den nødvendige join er allerede inkluderet, og den ser ud som alt hvad der ville være nødvendigt er dette:
@Where(clause = "ppg_status <> 'D'")
Det viser sig dog at ikke arbejd som Hibernate foran det forkerte tabelalias:
where
(
purchasepr0_.ppg_status <> 'D'
)
and purchasepr0_.crd_id=?
Desværre, når et alias først er tildelt en tabel, er det ikke muligt at bruge det originale tabelnavn - så purchase_product_group.ppg_status <> 'D'
ville ikke virke. Og jeg er ikke bekendt med en måde at bestemme aliasnavnet, der bruges af Hibernate programmæssigt - så på nuværende tidspunkt ser valget ud til at være enten hårdkode aliasnavnet, der viser sig at blive brugt af Hibernate (dvs. purchasepr1_.ppg_status <> 'D'
) eller for at bruge exists
metode beskrevet i spørgsmålet.
OPDATERING: Ved yderligere undersøgelse viser det sig, at hårdkodning af aliasnavnene ikke altid er brugbare. Her er en kriterieforespørgsel, hvor dette ikke ville virke:
/* 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=?
Til sidst forlod jeg @Where
tilgang og brugte @Filter
i stedet, hvilket virker meget bedre, da det kan acceptere HQL i stedet for databasefeltnavne, og når det anvendes på enhedsniveau, vil det påvirke relationer (i modsætning til @Where
).