S'il vous plaît, aidez-moi à comprendre où utiliser un JOIN régulier et où 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?
Dans ces deux requêtes, vous utilisez JOIN pour interroger tous les employés auxquels au moins un département est associé.
Mais la différence est la suivante: dans la première requête, vous ne renvoyez que les Employés pour Hibernate. 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 créer une nouvelle requête pour consulter à nouveau la base de données afin de voir les départements de chaque employé.
Vous pouvez utiliser la deuxième requête lorsque vous êtes certain d'avoir besoin du département de chaque employé. Si vous n'avez pas besoin du département, utilisez la première requête.
Je vous recommande de lire ce lien si vous devez 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 services continuent à être renvoyés, c'est que votre correspondance entre l'employé et le service (un @OneToMany
) est définie avec FetchType.EAGER
. Dans ce cas, toute requête HQL (avec fetch
ou non) avec FROM Employee
apportera tous les départements. N'oubliez pas que tous les mappages * ToOne (@ManyToOne
et @OneToOne
) sont EAGER par défaut.
dans ce lien je l'ai mentionné auparavant sur le commentaire, lisez cette partie:
Une jointure "fetch" permet d’initialiser des associations ou des ensembles de valeurs avec leurs objets parents à l’aide d’une seule sélection. Ceci est particulièrement utile dans le cas d'une collection. Il remplace en fait les déclarations de jointure externe et différée du fichier de mappage pour les associations et les collections.
cet effet "JOIN FETCH" aura son effet si vous avez la propriété (fetch = FetchType.LAZY) pour une collection dans l'entité (exemple ci-dessous).
Et ce n'est que l'effet de la méthode de "quand la requête devrait se passer". Et vous devez aussi savoir this :
hibernate a deux notions orthogonales: quand l’association est-elle extraite et comment est-elle extraite? Il est important de ne pas les confondre. Nous utilisons fetch pour optimiser les performances. Nous pouvons utiliser paresseux pour définir un contrat pour quelles données sont toujours disponibles dans une instance détachée d'une classe particulière.
quand l'association est-elle récupérée -> votre type "FETCH"
comment est-il récupéré -> Joindre/sélectionner/sous-sélectionner/lot
Dans votre cas, FETCH n'aura son effet que si vous avez le département en tant qu'ensemble dans Employee, quelque chose comme ceci dans l'entité:
@OneToMany(fetch = FetchType.LAZY)
private Set<Department> department;
quand vous utilisez
FROM Employee emp
JOIN FETCH emp.department dep
vous obtiendrez emp
et emp.dep
. quand vous n'avez pas utilisé chercher, vous pouvez toujours obtenir emp.dep
mais hibernate traitera une autre sélection dans la base de données pour obtenir cet ensemble de services.
il s’agit donc simplement d’optimiser les performances. Vous voulez obtenir tous les résultats (que vous en ayez besoin ou non) en une seule requête (extraction anticipée), ou vous souhaitez l’interroger ultérieurement lorsque vous en avez besoin (extraction différée).
Utilisez une extraction rapide lorsque vous avez besoin d’obtenir de petites données avec une seule requête (une seule grande requête). Ou utilisez la récupération paresseuse pour interroger ce dont vous avez besoin (beaucoup de requêtes plus petites).
utilisez fetch quand:
pas de grande collection inutile à l'intérieur de cette entité que vous êtes sur le point d'obtenir
communication du serveur d'application vers serveur de base de données trop éloignée et nécessite une longue période
vous pouvez avoir besoin de cette collection plus tard si vous n’avez pas accès à celle-ci ( en dehors de du transaction ( méthode/classe)
Si le mappage @oneToOne est défini sur FetchType.LAZY et que vous utilisez une seconde requête (car vous devez charger des objets Department dans le cadre des objets Employee), Hibernate émettra des requêtes pour extraire des objets Department pour chaque objet Employee. il va chercher chez DB. Plus tard dans le code, vous pourrez accéder aux objets Département via l'association à valeur unique Employé à département et Hibernate n'émettra aucune requête pour extraire un objet Département pour l'employé donné. Rappelez-vous 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.
Dherik: Je ne suis pas sûr de ce que vous dites. Lorsque vous n'utilisez pas chercher, le résultat sera de type: List<Object[ ]>
, ce qui signifie une liste de tables Object et non une liste d'employés.
Object[0] refers an Employee entity
Object[1] refers a Departement entity
Lorsque vous utilisez la fonction de récupération, il n’ya qu’une sélection et le résultat est la liste Employé List<Employee>
contenant la liste des services. Il remplace la déclaration paresseuse de l'entité.