8 votes

JPA et Hibernate : Eager loading effectuant des requêtes ultérieures pour récupérer toutes les données, au lieu de le faire en une seule requête.

J'ai le doute suivant. J'aimerais savoir pourquoi, en utilisant JPA et Hibernate, lorsqu'on effectue un chargement Eager dans une base de données de type ManyToOne o OneToMany il appelle la base de données afin d'obtenir les informations sur l'entité, mais il produit en outre des requêtes ultérieures pour récupérer chaque enfant.

D'un autre côté, lorsqu'on utilise une requête avec JOIN FETCH, la requête est exécutée comme je m'y attendais, en prenant les informations en une seule fois, puisque le fetchType est indiqué comme "EAGER".

Voici un exemple simple :

J'ai la classe Student qui a une relation ManyToOne avec la classe Classroom.

@Entity
@Table(name = "STUDENT")
public class Student {

@ManyToOne(optional = true, fetch = FetchType.EAGER)
        @JoinColumn(name = "ClassroomID")
        private Classroom mainClass;

De l'autre côté, il y a la classe nommée Classroom comme suit :

@Entity
public class Classroom {

@OneToMany(cascade = CascadeType.ALL, mappedBy = "mainClass", fetch = FetchType.EAGER)
private List<Student> studentsList;

Lorsqu'il obtient l'objet Salle de classe, il effectue une requête pour obtenir les informations le concernant et des requêtes ultérieures pour obtenir les informations de chaque élève contenu dans l'objet liste des étudiants pour chaque objet classRoom.

Première requête :

Hibernate: 
/* SELECT
         r 
     FROM
         Classroom r 
     LEFT JOIN
         r.classStudents */ 

     select
         classroom0_.id as id1_0_,
         classroom0_.number as number2_0_ 
     from
         Classroom classroom0_ 
     left outer join
         STUDENT classstude1_ 
             on classroom0_.id=classstude1_.ClassroomID

Puis il exécute la requête suivante autant de fois que d'étudiants affectés à chaque classe.

  Hibernate: 
      /* load one-to-many com.hw.access.Classroom.classStudents */ 
      select
          classstude0_.ClassroomID as Classroo4_0_1_,
          classstude0_.id as id1_1_1_,
          classstude0_.id as id1_1_0_,
          classstude0_.FIRST_NAME as FIRST_NA2_1_0_,
          classstude0_.LAST_NAME as LAST_NAM3_1_0_,
          classstude0_.ClassroomID as Classroo4_1_0_ 
      from
          STUDENT classstude0_ 
      where
          classstude0_.ClassroomID=?

La question est la suivante : Pourquoi ne prend-il pas les informations en une seule fois ? Pourquoi ne prend-il pas les informations en une seule requête ? Comme il exécute déjà la clause de jonction .

Pourquoi juste en ajoutant Aller chercher explicitement dans la requête, il fait ce qui lui est demandé ?

Par exemple :

SELECT
         r 
     FROM
         Classroom r 
     LEFT JOIN FETCH
         r.classStudents */ 

Et ensuite, la requête de sortie reprend toutes les informations en une seule requête :

Hibernate: 

        select
              classroom0_.id as id1_0_0_,
              classstude1_.id as id1_1_1_,
              classroom0_.number as number2_0_0_,
              classstude1_.FIRST_NAME as FIRST_NA2_1_1_,
              classstude1_.LAST_NAME as LAST_NAM3_1_1_,
              classstude1_.ClassroomID as Classroo4_1_1_,
              classstude1_.ClassroomID as Classroo4_0_0__,
              classstude1_.id as id1_1_0__ 
          from
              Classroom classroom0_ 
          left outer join
              STUDENT classstude1_ 
                  on classroom0_.id=classstude1_.ClassroomID

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X