Bli kjent med LazyCollectionOption.EXTRA

Men av størst interesse er LazyCollectionOption.EXTRA-verdien. Hvis du spesifiserer det som verdien av @LazyCollection -kommentaren , vil Hibernate forsinke lasting av elementene i samlingen så lenge som mulig.

Hvis du prøver å finne antall elementer i en samling:

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

For all denne koden vil Hibernate bare utføre én spørring:

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

Men hvis du ønsker å få én kommentar fra samlingen, for eksempel nummer 3:

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

Da oppstår spørsmålet: hvordan skal Hibernate vite at elementet er det tredje uten å laste inn alle elementene i minnet?

For å løse dette problemet foreslås det å lage en ekstra kolonne i kommentartabellen, som vil lagre ordensnummeret til kommentaren i kommentarsamlingen. Og også for dette trenger du en spesiell merknad - @OrderColumn .

Slik vil løsningen se ut:

@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;
}

Den største fordelen med LazyCollectionOption.EXTRA

Vi ser den sterkeste fordelen med LazyCollectionOption.EXTRA når vi spesifiserer det med @ManyToMany -kommentaren . La oss ta vår gamle sak der vi har en ansatt, en oppgave, og vi kan tildele mange oppgaver til én bruker.

Java-klassene våre ser slik ut:

Ansatt klasse :

@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>();

}

Og EmployeeTask-klassen :

@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>();

}

Og for å legge til en oppgave til regissøren, må du skrive noe slikt som denne koden:

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

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

Så hvis ansatte-feltet i Task-klassen har LazyCollectionOption.EXTRA-kommentaren, vil de ansattes samling (av Task-klassen) og oppgavesamlingen (av Employee-klassen) aldri bli lastet fra databasen i det hele tatt .

Når denne koden er utført, vil bare én post settes inn i tjenestetabellen for ansatte_task, som, som du husker, ser omtrent slik ut:

ansatt_oppgavetabell :
Ansatt ID task_id
1 1
2 2
5 3
5 4
5 5
4 7
6 8
4 101

Den tilføyde linjen er uthevet i grønt. For å legge til denne linjen trenger du ikke å laste inn samlinger fra databasen - Hibernate vil klare seg uten den. Dette er akkurat tilfellet når LazyCollectionOption.EXTRA øker hastigheten på arbeidet med databasen.

N+1 problem

Men selvfølgelig har denne modusen også en ulempe. For eksempel genererer LazyCollectionOption.EXTRA-kommentaren et N+1-problem .

Hvis du bestemmer deg for å gå gjennom alle brukerens kommentarer:

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

Deretter vil Hibernate kjøre på en separat forespørsel for hvert kommentarobjekt. Og også et ekstra spørsmål for å få tellingen av alle kommentarer. Dette kan redusere koden betydelig.

Hvis brukeren din har 1000 kommentarer, vil Hibernate gjøre 1001 spørringer til databasen for å utføre denne koden, selv om det kan gjøres med en. Hvis du visste på forhånd at du ville trenge alle objektene i denne klassen.