JPA/JPQL REJOINDRE sous-sélection/sous-Requête
J'ai de la difficulté à traduire facilement de l'instruction SQL pour JPQL, en raison d'une sous-requête, ce qui n'est pas pris en charge par JPQL.
Quelqu'un peut me donner un indice, comment faire pour obtenir le même résultat JPQL ou JPA2 Critères d'API?
Donné (Simplifié de fausses données pour démontrer le problème):
CREATE TABLE person (id integer, name text);
CREATE TABLE phone (id integer, person_id integer, type text, number text);
INSERT INTO person VALUES (1, "John");
INSERT INTO person VALUES (2, "Mike");
INSERT INTO person VALUES (3, "Paul");
INSERT INTO person VALUES (4, "Walter");
INSERT INTO phone VALUES (1, 1, "MOBILE", "+49-123-11111");
INSERT INTO phone VALUES (2, 1, "HOME" , "+49-123-22222");
INSERT INTO phone VALUES (3, 2, "WORK" , "+49-123-33333");
INSERT INTO phone VALUES (4, 4, "MOBILE", "+49-123-44444");
-- Select all from person and their mobile number if possible
-- This query has to be translated to JPQL
SELECT person.name, mobile.number FROM person LEFT JOIN (
SELECT * FROM phone WHERE type = "MOBILE"
) AS mobile ON person.id = mobile.person_id;
Résultat attendu:
| name | number |
|-------- | ---------------|
| John | +49-123-11111 |
| Mike | |
| Paul | |
| Walter | +49-123-44444 |
Java:
class Person {
String name;
List<Phone> phones;
}
class Phone {
String type;
String number;
}
JPQL (ne fonctionne pas comme prévu 🙁 ):
SELECT person.name, phone.number FROM Person person
LEFT JOIN person.phones AS phone
WHERE phone.type = "MOBILE"
OriginalL'auteur Joachim Schmidt | 2015-07-13
Vous devez vous connecter pour publier un commentaire.
Vous pouvez également remplacer le
ON
mot-clé spécifique d'hibernateWITH
:OriginalL'auteur Dragan Bozanovic
Essayez ceci:
OriginalL'auteur Paul Vargas
Tout d'abord selon le Persistance Java Wikibook certains JPA fournisseurs comme EclipseLink et TopLink soutien sous sélectionne dans la
FROM
clause - bien que ce n'est pas définie dans l'accord de projet conjoint spec.En JPA 2.1 vous pouvez utiliser
LEFT JOIN
avecON
:Avant JPA 2.1 vous pouvez utiliser un
case
expression:Mais ce sera juste essuyer toutes aucun-mobile numéros de téléphone - alors il y aura une ligne pour chaque numéro de téléphone d'une personne, même si il/elle a plus d'un numéro de téléphone qui n'est pas un numéro de mobile.
Vous pouvez utiliser le liste d'agrégation fonction de votre base de données (comme
LISTAGG
dans Oracle), si votre fournisseur JPA rend ces correctement (Hibernate ne dans la plupart des cas). Cela aurait du sens pour les deux premières options en tant que bien si une personne peut avoir plus d'un numéro de téléphone mobile.OriginalL'auteur Tobias Liefke