LazyCollectionOption.EXTRA'yı tanıma

Ancak en ilgi çekici olanı LazyCollectionOption.EXTRA değeridir. Bunu @LazyCollection ek açıklamasının değeri olarak belirtirseniz , Hazırda Bekletme, koleksiyon öğelerinin yüklenmesini mümkün olduğu kadar geciktirir.

Bir koleksiyondaki öğelerin sayısını almaya çalışırsanız:

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

Ardından, tüm bu kod için Hazırda Bekletme yalnızca bir sorgu yürütür:

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

Ancak, koleksiyondan bir yorum almak istiyorsanız, örneğin 3 numara:

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

O zaman şu soru ortaya çıkıyor: Hazırda Bekletme, tüm öğeleri belleğe yüklemeden öğenin üçüncü olduğunu nasıl bilebilir?

Bu sorunu çözmek için, yorum tablosunda, yorum koleksiyonundaki yorumun sıra numarasını saklayacak ek bir sütun yapılması önerilir. Ayrıca bunun için özel bir açıklamaya ihtiyacınız var - @OrderColumn .

İşte bu çözümün nasıl görüneceği:

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

LazyCollectionOption.EXTRA'nın ana avantajı

LazyCollectionOption.EXTRA'nın en güçlü avantajını @ManyToMany ek açıklamasıyla belirttiğimizde görüyoruz . Bir Çalışanın, bir Görevin olduğu eski durumumuzu ele alalım ve bir kullanıcıya birçok görev atayabiliriz.

Java sınıflarımız şöyle görünür:

Çalışan sınıfı :

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

}

Ve EmployeeTask sınıfı :

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

}

Yönetmene bir görev eklemek için şu kod gibi bir şey yazmanız gerekir:

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

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

Bu nedenle, Task sınıfındaki çalışanlar alanı LazyCollectionOption.EXTRA ek açıklamasına sahipse, o zaman (Task sınıfının) staff koleksiyonu ve (Responant sınıfının) görev koleksiyonu hiçbir zaman veritabanından yüklenmeyecektir .

Bu kod yürütüldüğünde, staff_task hizmet tablosuna yalnızca bir kayıt eklenecektir, bu, hatırladığınız gibi şuna benzer:

çalışan_görev tablosu :
Çalışan kimliği görev_kimliği
1 1
2 2
5 3
5 4
5 5
4 7
6 8
4 101

Eklenen satır yeşil renkle vurgulanır. Bu satırı eklemek için veritabanından koleksiyonlar yüklemenize gerek yoktur - Hibernate onsuz yapacaktır. LazyCollectionOption.EXTRA veritabanıyla çalışmayı büyük ölçüde hızlandırdığında durum tam olarak budur.

N+1 sorunu

Ancak, elbette, bu modun da bir dezavantajı var. Örneğin, LazyCollectionOption.EXTRA ek açıklaması bir N+1 Problemi oluşturur .

Kullanıcınızın tüm yorumlarını gözden geçirmeye karar verirseniz:

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

Ardından Hazırda Bekletme, her Yorum nesnesi için ayrı bir istekte yürütülür. Ayrıca tüm yorumların sayısını almak için bir ek sorgu daha. Bu, kodu önemli ölçüde yavaşlatabilir.

Kullanıcınızın 1000 yorumu varsa, Hibernate bu kodu yürütmek için veritabanına 1001 sorgu yapacaktır, ancak bir tanesiyle de yapabilir. Bu sınıfın tüm nesnelerine ihtiyacınız olacağını önceden bilseydiniz.