JavaRush /Kurslar /All lectures for UZ purposes /LazyCollectionOption.EXTRA

LazyCollectionOption.EXTRA

All lectures for UZ purposes
Daraja, Dars
Mavjud

LazyCollectionOption.EXTRA bilan tanishamiz

Ammo eng katta qiziqish LazyCollectionOption.EXTRA qiymatida. Agar sen bu qiymatni @LazyCollection annotatsiyasiga kiritadigan bo'lsang, Hibernate kolleksiyani yuklashni iloji boricha kechiktiradi.

Agar kolleksiya elementlarining sonini olishga harakat qilsang:


User user = session.load(User.class, 1);             	
List<Comment> comments = user.getComments();
int count = commetns.size(); // комментарий: "количество"

Bu kod uchun Hibernate faqat bitta so'rovni bajargan bo'ladi:

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

Lekin agar sen kolleksiyadan bitta, masalan, 3-raqamli kommentni olishni xohlasang:


User user = session.load(User.class, 1);             	
List<Comment> comments = user.getComments();
Comment comment = commetns.get(3); // комментарий: "получаем третий комментарий"

Unda savol tug'iladi: Hibernate qanday qilib barcha elementlarni xotiraga yuklamasdan 3-element ekanligini biladi?

Bu muammoni hal qilish uchun comment jadvalida qo'shimcha kolonka qo'shishni taklif qilishadi, bu kolonka kolleksiyadagi kommentlar tartib raqamini saqlaydi. Shuningdek, buning uchun maxsus annotatsiya — @OrderColumn kerak bo'ladi.

Bu yechim qanday ko'rinishda bo'ladi:


@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 ning asosiy afzalligi

LazyCollectionOption.EXTRA ning asosiy afzalligi annotatsiya @ManyToMany ga berilganda kuzatiladi. Eski misolimizga qaytaylik, bizda Employee, Task bor va bitta foydalanuvchiga ko'p vazifalarni tayinlash mumkin.

Bizning Java-klasslarimiz shunday ko'rinishda:

Employee klassi:


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

Va EmployeeTask klassi:


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

Direktorga vazifa qo'shish uchun taxminan shunday kod yoziladi:


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

Agar Task klassidagi employees maydoni LazyCollectionOption.EXTRA annotatsiyasiga ega bo'lsa, vazifalar va task kolleksiyalari xech qachon bazadan yuklanmaydi.

Bu kod bajarilganda employee_task nomli xizmat jadvaliga faqat bitta yozuv qo'shiladi. Bu jadval taxminan shunday ko'rinishda:

employee_task jadvali:
employee_id task_id
1 1
2 2
5 3
5 4
5 5
4 7
6 8
4 101

Yashil rangda qo'shilgan qator ko'rsatilgan. Bu qatorda qo'shish uchun kolleksiyalarni bazadan yuklash shart emas, Hibernate buni qila oladi. Bu LazyCollectionOption.EXTRA asosiy afzalligi ekanligini ko'rsatadi.

N+1 Muammo

Biroq, albatta, bu rejimning ham o'ziga xos muammosi bor. LazyCollectionOption.EXTRA annotatsiyasi N+1 Muammo ni keltirib chiqaradi.

Agar sen foydalanuvchingning barcha kommentlari ustida yurmoqchi bo'lsang:


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

Hibernate har bir Comment obyekti uchun alohida so'rov bajaradi. Shuningdek, barcha kommentlar sonini olish uchun yana bir qo'shimcha so'rov. Bu kodni bajarishni sezilarli darajada sekinlashtirishi mumkin.

Agar foydalanuvchingda 1000 ta komentariy bo'lsa, bu kodni bajarish uchun Hibernate 1001 ta so'rov bajaradi, bu esa faqat bir marta ham bajarilishi mumkin edi. Agar u oldindan bilsa edi, barcha obyektlar kerakligini.

Izohlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION