J'ai 2 entités, A
et B
. Ils sont liés mais je ne veux pas ajouter le mappage de relation aux beans.
Comment utiliser la jointure externe gauche entre A
et B
en utilisant HQL ou des critères ?
Il existe des solutions de contournement pour cela,
J'étais toujours en train de revenir sur ces 2 options, y a-t-il une alternative pour cela? Ou ce n'est pas possible?
Actuellement, le style thêta pour joindre les classes non liées dans la clause where en utilisant HQL ne prend en charge que la jointure interne.
La demande pour supporter la jointure externe dans une telle situation est actuellement la 3ème amélioration la plus votée mais je ne pense pas que cette fonctionnalité sera implémentée dans la fonctionnalité proche car elle nécessite la réimplémentation de l'analyseur de requêtes actuel basé sur ANTLER d'abord, ce qui semble être une tâche IMO gigantesque.
Si vous insistez pour utiliser le HQL pour effectuer la jointure gauche sans ajouter la relation entre A et B, vous pouvez utiliser l'option 3 pour effectuer la jointure interne en premier, puis utilisez le HQL suivant
from A a where a.some not in ( select b.some from B)
pour découvrir tous les A qui ne peuvent pas rejoindre B et combiner les résultats par programme.
Mise à jour
Depuis la version 5.1.0 HHH-16 (jointures explicites sur les classes non liées) est corrigé et nous devrions pouvoir rejoindre les entités non liées.
Comme l'a dit Ken Chan, vous ne pouvez pas le faire directement dans une seule requête HQL.
Concernant vos trois possibilités:
Si, pour des raisons particulières, vous ne voulez vraiment pas ajouter la relation, vous pouvez diviser la requête en deux requêtes individuelles et joindre le résultat manuellement en Java, par exemple comme ceci:
Query qa = session.createQuery("from A a");
List la = qa.list();
Query qb = session.createQuery("select distinct b.* from B b, A a where a.some=b.some");
List lb = qb.list();
Map bMap = new HashMap();
for (B b : lb) {
bMap.put(b.getId(), b);
}
/* example with for loop */
for (A a : la) {
B b = bMap.get(a.getForeignKeyForB());
/* now you have A a and the outer joined B b and you can do with them what you want */
...
}
Cette solution a (presque) le même coût en temps d'exécution et en mémoire que la jointure externe dans la base de données (solution 2.). C'est juste un peu plus Java code.
(La solution est similaire à celle proposée par Ken Chan, mais elle évite le "pas dedans" et la sélection interne, qui peuvent toutes deux être inefficaces dans la base de données.)
Si vous savez que pour chaque A, il y a au maximum 1 B, vous pouvez également utiliser une sous-requête.
Par exemple:
select a, (select b from B b where b.some = a.some)
from A a
Si vous savez qu'il existe au moins 1 B, vous pouvez également utiliser la requête suivante, mais elle n'est pas recommandée car il s'agit d'un hack:
select a, (select b4 from B b4 where b4=b and b4.some=a.some) from A a, B b
where a.some=b.some or (a.some not in (select b2.some from B b2)
and b.id = (select min(b3.id) from B b3))