Poznajemy LazyCollectionOption.EXTRA

Jednak najbardziej interesująca jest wartość LazyCollectionOption.EXTRA. Jeśli określisz to jako wartość adnotacji @LazyCollection , Hibernate opóźni ładowanie elementów kolekcji tak długo, jak to możliwe.

Jeśli spróbujesz uzyskać liczbę elementów w kolekcji:

User user = session.load(User.class, 1);
List<Comment> comments = user.getComments();
int count = commetns.size();

Następnie dla całego tego kodu Hibernate wykona tylko jedno zapytanie:

SELECT COUNT(id) FROM comment WHERE user_id = 1;

Jeśli jednak chcesz uzyskać jeden komentarz z kolekcji, na przykład numer 3:

User user = session.load(User.class, 1);
List<Comment> comments = user.getComments();
Comment comment = commetns.get(3);

Wtedy pojawia się pytanie: skąd Hibernate ma wiedzieć, że element jest trzeci bez załadowania wszystkich elementów do pamięci?

Aby rozwiązać ten problem, proponuje się utworzenie dodatkowej kolumny w tabeli komentarzy, która będzie przechowywać numer porządkowy komentarza w zbiorze komentarzy. A także do tego potrzebujesz specjalnej adnotacji - @OrderColumn .

Oto jak wyglądałoby to rozwiązanie:

@Entity
@Table(name=”user”)
class User {
   @Column(name=”id”)
   public Integer id;

   @OneToMany(cascade = CascadeType.ALL)
   @LazyCollection(LazyCollectionOption.EXTRA)
   @OrderColumn(name = "order_id")
   public List<Comment> comments;
}

Główną zaletą LazyCollectionOption.EXTRA

Największą zaletę LazyCollectionOption.EXTRA widzimy, gdy określamy ją za pomocą adnotacji @ManyToMany . Weźmy nasz stary przypadek, w którym mamy Pracownika, Zadanie i możemy przypisać wiele zadań jednemu użytkownikowi.

Nasze klasy Java wyglądają tak:

Klasa pracownika :

@Entity
@Table(name=”employee”)
class Employee {
   @Column(name=”id”)
   public Integer id;

   @ManyToMany(cascade = CascadeType.ALL)
   @JoinTable(name="employee_task",
       	joinColumns=  @JoinColumn(name="employee_id", referencedColumnName="id"),
       	inverseJoinColumns= @JoinColumn(name="task_id", referencedColumnName="id") )
   @LazyCollection(LazyCollectionOption.EXTRA)
   private Set<EmployeeTask> tasks = new HashSet<EmployeeTask>();

}

I klasa EmployeeTask :

@Entity
@Table(name=”task”)
class EmployeeTask {
   @Column(name=”id”)
   public Integer id;

   @ManyToMany(cascade = CascadeType.ALL)
   @JoinTable(name="employee_task",
       	joinColumns=  @JoinColumn(name="task_id", referencedColumnName="id"),
       	inverseJoinColumns= @JoinColumn(name=" employee_id", referencedColumnName="id") )
   @LazyCollection(LazyCollectionOption.EXTRA)
   private Set<Employee> employees = new HashSet<Employee>();

}

Aby dodać zadanie do dyrektora, musisz napisać coś takiego jak ten kod:

Employee director = session.find(Employee.class, 4);
EmployeeTask task = session.find(EmployeeTask.class, 101);
task.employees.add(director);

session.update(task);
session.flush();

Jeśli więc pole pracowników w klasie Zadanie ma adnotację LazyCollectionOption.EXTRA, to kolekcja pracowników (klasy Zadanie) i kolekcja zadań (klasy Pracownik) nigdy nie zostaną wczytane z bazy danych .

Po wykonaniu tego kodu do tabeli usługi pracownik_zadanie zostanie wstawiony tylko jeden rekord, który, jak pamiętasz, wygląda mniej więcej tak:

tabela_zadanie_pracownika :
dowód pracownika identyfikator_zadania
1 1
2 2
5 3
5 4
5 5
4 7
6 8
4 101

Dodana linia jest podświetlona na zielono. Aby dodać tę linię, nie trzeba ładować kolekcji z bazy danych - Hibernate poradzi sobie bez niej. Tak właśnie jest w przypadku, gdy LazyCollectionOption.EXTRA znacznie przyspiesza pracę z bazą danych.

Problem N+1

Ale oczywiście ten tryb ma również wadę. Na przykład adnotacja LazyCollectionOption.EXTRA generuje problem N+1 .

Jeśli zdecydujesz się przejrzeć wszystkie komentarze użytkowników:

User user = session.load(User.class, 1);
List<Comment> comments = user.getComments();
for (Comment comment : comments) {
    System.out.println(comment);
}

Następnie Hibernate wykona osobne żądanie dla każdego obiektu komentarza. A także jeszcze jedno dodatkowe zapytanie, aby uzyskać liczbę wszystkich komentarzy. Może to znacznie spowolnić kod.

Jeśli twój użytkownik ma 1000 komentarzy, Hibernate wykona 1001 zapytań do bazy danych, aby wykonać ten kod, chociaż może to zrobić z jednym. Gdybyś wiedział z góry, że będziesz potrzebować wszystkich obiektów tej klasy.