S'il vous plaît, aidez-moi à comprendre où utiliser un JOIN régulier et où un JOIN FETCH.
Par exemple, si nous avons ces deux requêtes
FROM Employee emp
JOIN emp.department dep
et
FROM Employee emp
JOIN FETCH emp.department dep
Y a-t-il une différence entre eux? Si oui, lequel utiliser quand?
Réponses:
Dans ces deux requêtes, vous utilisez JOIN pour interroger tous les employés auxquels au moins un service est associé.
Mais la différence est la suivante: dans la première requête, vous ne renvoyez que les employés pour la mise en veille prolongée. Dans la deuxième requête, vous renvoyez les employés et tous les départements associés.
Ainsi, si vous utilisez la deuxième requête, vous n'aurez pas besoin de faire une nouvelle requête pour accéder à nouveau à la base de données pour voir les départements de chaque employé.
Vous pouvez utiliser la deuxième requête lorsque vous êtes sûr que vous aurez besoin du département de chaque employé. Si vous n'avez pas besoin du département, utilisez la première requête.
Je recommande de lire ce lien si vous avez besoin d'appliquer une condition WHERE (ce dont vous aurez probablement besoin): Comment exprimer correctement JPQL "join fetch" avec la clause "where" en tant que JPA 2 CriteriaQuery?
Mettre à jour
Si vous n'utilisez pas
fetch
et que les départements continuent d'être retournés, c'est parce que votre mappage entre l'employé et le département (a@OneToMany
) est réglé avecFetchType.EAGER
. Dans ce cas, toutefetch
requête HQL (avec ou non) avecFROM Employee
apportera tous les départements. N'oubliez pas que tous les mappages * ToOne (@ManyToOne
et@OneToOne
) sont EAGER par défaut.la source
fetch
convient de mentionner qu'il doit être utilisé si (en utilisant notre exemple) vous souhaitez commander par un attribut de service. Sinon, (valable au moins pour PG), vous pourriez obtenirERROR: for SELECT DISTINCT, ORDER BY expressions must appear in select list
dans ce lien que j'ai mentionné précédemment dans le commentaire, lisez cette partie:
ce "JOIN FETCH" aura son effet si vous avez la propriété (fetch = FetchType.LAZY) pour une collection à l'intérieur d'une entité (exemple ci-dessous).
Et ce n'est que l'effet de la méthode "quand la requête doit se produire". Et vous devez également savoir ceci :
quand l'association est-elle récupérée -> votre type "FETCH"
comment est-il récupéré -> Rejoindre / sélectionner / Sous-sélectionner / Lot
Dans votre cas, FETCH n'aura son effet que si vous avez un département comme ensemble dans Employee, quelque chose comme ceci dans l'entité:
quand vous utilisez
vous obtiendrez
emp
etemp.dep
. quand vous n'avez pas utilisé fetch, vous pouvez toujours obteniremp.dep
mais hibernate traitera une autre sélection dans la base de données pour obtenir cet ensemble de services.donc c'est juste une question de réglage des performances, à propos de vous voulez obtenir tous les résultats (vous en avez besoin ou non) en une seule requête (récupération impatiente), ou vous voulez l'interroger plus tard lorsque vous en avez besoin (récupération paresseuse).
Utilisez la récupération rapide lorsque vous avez besoin d'obtenir de petites données avec une sélection (une grande requête). Ou utilisez la récupération paresseuse pour interroger ce dont vous avez besoin plus tard (plusieurs requêtes plus petites).
utilisez fetch quand:
pas de grande collection / ensemble inutile à l' intérieur de cette entité que vous êtes sur le point d'obtenir
la communication entre le serveur d'applications et le serveur de base de données est trop longue et nécessite beaucoup de temps
vous pouvez avoir besoin de cette collection plus tard lorsque vous n'y avez pas accès (en dehors de la méthode / classe transactionnelle )
la source
List
au lieu d'unSet
?FETCH
mot - clé dans une instruction JPQL implique-t-elle une propriété rapidement récupérée?JOINDRE
Lors de l'utilisation
JOIN
contre des associations d'entité, JPA générera un JOIN entre l'entité parente et les tables d'entité enfant dans l'instruction SQL générée.Donc, en prenant votre exemple, lors de l'exécution de cette requête JPQL:
Hibernate va générer l'instruction SQL suivante:
REJOINDRE FETCH
Ainsi, par rapport à
JOIN
, leJOIN FETCH
vous permet de projeter les colonnes de la table de jointure dans laSELECT
clause de l'instruction SQL générée.Ainsi, dans votre exemple, lors de l'exécution de cette requête JPQL:
Hibernate va générer l'instruction SQL suivante:
C'est également
JOIN FETCH
un excellent moyen de résoudre le problèmeLazyInitializationException
lors de l'utilisation d'Hibernate, car vous pouvez initialiser les associations d'entités à l'aide de laFetchType.LAZY
stratégie de récupération avec l'entité principale que vous récupérez.la source
Si le
@oneToOne
mappage est défini surFetchType.LAZY
et que vous utilisez une deuxième requête (car vous avez besoin que les objets Department soient chargés dans le cadre des objets Employee), Hibernate émettra des requêtes pour récupérer des objets Department pour chaque objet Employee qu'il récupère dans la base de données.Plus tard, dans le code, vous pourrez accéder aux objets Department via une association à valeur unique Employé-Département et Hibernate n'émettra aucune requête pour récupérer l'objet Service pour l'employé donné.
N'oubliez pas qu'Hibernate émet toujours des requêtes égales au nombre d'employés qu'il a récupérés. Hibernate émettra le même nombre de requêtes dans les deux requêtes ci-dessus, si vous souhaitez accéder aux objets Department de tous les objets Employee
la source
Dherik: Je ne suis pas sûr de ce que vous dites, lorsque vous n'utilisez pas de récupération, le résultat sera de type:
List<Object[ ]>
ce qui signifie une liste de tables d'objets et non une liste d'employés.Lorsque vous utilisez fetch, il n'y a qu'une seule sélection et le résultat est la liste des employés
List<Employee>
contenant la liste des départements. Il remplace la déclaration paresseuse de l'entité.la source
fetch
, votre requête renverra uniquement les employés. Si les départements, même dans ce cas, continuent à être retournés, c'est parce que votre mappage entre Employee et Department (un @OneToMany) est défini avec FetchType.EAGER. Dans ce cas, toutefetch
requête HQL (avec ou non) avecFROM Employee
apportera tous les départements.@OneToMany(fetch = FetchType.EAGER
). Si ce n'est pas le cas, les Départements ne seront pas restitués.select
été fait dans le HQL. EssayezSELECT emp FROM Employee emp JOIN FETCH emp.department dep
. JPA / Hibernate ont ce comportement d'un retourList
deObject[]
quand vous OMMISSIONS laSELECT
partie.