Lær LazyCollectionOption.EXTRA at kende

Men af ​​størst interesse er LazyCollectionOption.EXTRA-værdien. Hvis du angiver det som værdien af ​​@LazyCollection- annotationen , vil Hibernate forsinke indlæsningen af ​​samlingens elementer så længe som muligt.

Hvis du forsøger at få antallet af elementer i en samling:

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

Så for al denne kode vil Hibernate kun udføre én forespørgsel:

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

Men hvis du ønsker at 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);

Så opstår spørgsmålet: hvordan skal Hibernate vide, at elementet er det tredje uden at indlæse alle elementerne i hukommelsen?

For at løse dette problem foreslås det at lave en ekstra kolonne i kommentartabellen, som gemmer kommentarens ordensnummer i kommentarsamlingen. Og også til dette har du brug for en speciel anmærkning - @OrderColumn .

Sådan ser løsningen ud:

@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 fordel ved LazyCollectionOption.EXTRA

Vi ser den største fordel ved LazyCollectionOption.EXTRA, når vi angiver det med @ManyToMany -annotationen . Lad os tage vores gamle case, hvor vi har en medarbejder, en opgave, og vi kan tildele mange opgaver til én bruger.

Vores Java-klasser ser sådan ud:

Medarbejderklasse :

@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 at tilføje en opgave til instruktøren, skal du skrive noget som denne kode:

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 medarbejderfeltet i Task-klassen har LazyCollectionOption.EXTRA-annotationen, så vil medarbejdersamlingen (af Task-klassen) og opgavesamlingen (af Employee-klassen) aldrig blive indlæst fra databasen overhovedet .

Når denne kode udføres, vil der kun blive indsat én post i tjenestetabellen medarbejder_task, som, som du husker, ser sådan ud:

medarbejder_opgave tabel :
Medarbejder-ID opgave-id
1 1
2 2
5 3
5 4
5 5
4 7
6 8
4 101

Den tilføjede linje er fremhævet med grønt. For at tilføje denne linje behøver du ikke at indlæse samlinger fra databasen - Hibernate vil klare sig uden den. Dette er præcis tilfældet, når LazyCollectionOption.EXTRA i høj grad fremskynder arbejdet med databasen.

N+1 problem

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

Hvis du beslutter dig for at gennemgå alle dine brugers kommentarer:

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

Så vil Hibernate udføre på en separat anmodning for hvert kommentarobjekt. Og også en yderligere forespørgsel for at få optællingen af ​​alle kommentarer. Dette kan sænke koden betydeligt.

Hvis din bruger har 1000 kommentarer, vil Hibernate lave 1001 forespørgsler til databasen for at udføre denne kode, selvom det kunne gøres med en. Hvis du vidste på forhånd, at du ville få brug for alle objekterne i denne klasse.