Problem n+1 zapytań w Hibernate


Problem n+1 zapytań w Hibernate

Problem n+1 zapytań (generowanie nadmiarowych zapytań) jest jednym z najbardziej znanych problemów, z jakimi muszą zmagać się programiści wykorzystujący w swoich projektach Hibernate. Kiedy kolekcja ładowana jest leniwie (Lazy loading) to hibernate zamiast jednego zapytania wykonuje n + 1 zapytań. Jedno zapytanie do pobrania listy obiektów zawierających wspomniane kolekcje oraz n zapytań do pobrania każdej kolekcji dla każdego pobranego wcześnie obiektu.

@Entity
public class Room {
    @Id
    @GeneratedValue
    private long id;
    
    @OneToMany
    private List <Item > items ;
    // getters & setters
}

@Entity
public class Item {
    @Id
    @GeneratedValue
    private long id;

    private String name ;
    // getters & setters
}

Dla każdego z N pokoi wykonywane jest zapytanie o jego przedmioty  (N razy przedmioty + 1 raz pokoje, w sumie N+1 zapytań)

Hibernate : select room0_ .id as id1_17_ from room_n_1_problem room0_

Hibernate : select items0_ . room as room3_9_0_ , items0_ .id as id1_9_0_ ,
items0_ .id as id1_9_1_ , items0_ . name as name2_9_1_ , items0_ . room as room3_9_1_
from item_n_1_problem items0_ where items0_ . room =?

Hibernate : select items0_ . room as room3_9_0_ ,
items0_ .id as id1_9_0_ , items0_ .id as id1_9_1_ , items0_ . name as name2_9_1_ ,
items0_ . room as room3_9_1_ from item_n_1_problem items0_
where items0_ . room =?

Rozwiązanie? Stworzenie zapytania z użyciem klauzuli JOIN FETCH:

SELECT DISTINCT u FROM Room r JOIN FETCH r. items

lub od JPA 2.1 wykorzystanie bardziej wyrafinowanej metody z użyciem adnotacji @NamedEntityGraphs.


Leave a comment

Your email address will not be published.


*