J'ai activé la journalisation SQL et examiné le résultat de la requête. Pour le cas ci-dessus, c'était ceci :
/* 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=?
Ainsi, la jointure nécessaire est déjà incluse et elle semble comme tout ce qu'il faudrait, c'est ceci :
@Where(clause = "ppg_status <> 'D'")
Cependant, il s'avère que non fonctionne comme Hibernate ajoute le mauvais alias de table :
where
(
purchasepr0_.ppg_status <> 'D'
)
and purchasepr0_.crd_id=?
Malheureusement, une fois qu'un alias est attribué à une table, il n'est pas possible d'utiliser le nom de la table d'origine - donc purchase_product_group.ppg_status <> 'D'
ne fonctionnerait pas. Et je ne suis pas au courant d'un moyen de déterminer le nom d'alias utilisé par Hibernate par programmation - donc à l'heure actuelle, le choix semble être soit de coder en dur le nom d'alias utilisé par Hibernate (c'est-à-dire purchasepr1_.ppg_status <> 'D'
) ou d'utiliser le exists
méthode décrite dans la question.
MISE À JOUR : Après une enquête plus approfondie, il s'avère que le codage en dur des noms d'alias n'est pas toujours réalisable. Voici une requête de critères où cela ne fonctionnerait pas :
/* 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=?
Au final j'ai abandonné le @Where
approche et utilisé @Filter
à la place, ce qui semble bien mieux car il peut accepter HQL plutôt que les noms de champs de base de données et lorsqu'il est appliqué au niveau de l'entité affectera les relations (contrairement à @Where
).