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.
GO TO FULL VERSION