JavaRush /Курсы /All lectures for GE purposes /LazyCollectionOption.EXTRA

LazyCollectionOption.EXTRA

All lectures for GE purposes
1 уровень , 294 лекция
Открыта

ვიცნობთ LazyCollectionOption.EXTRA

მაგრამ ყველაზე დიდი ინტერესი LazyCollectionOption.EXTRA-ის მნიშვნელობაშია. თუ შენ მიუთითებ მას როგორც ანოტაციის @LazyCollection მნიშვნელობას, მაშინ Hibernate მაქსიმალურად გადადებს კოლექციის ელემენტების ჩატვირთვას.

თუ შენ სცდი მიიღო კოლექციის ელემენტების რაოდენობა:


User user = session.load(User.class, 1);             	
List<Comment> comments = user.getComments();
int count = commetns.size(); // კომენტარების რაოდენობა

მაშინ ამ კოდის მთლიანი შესრულებისთვის Hibernate მხოლოდ ერთ შეკითხვას შეასრულებს:

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

თუმცა, თუ შენ გინდა მიიღო ერთი კომენტარი კოლექციიდან, მაგალითად, ნომერი 3:


User user = session.load(User.class, 1);             	
List<Comment> comments = user.getComments();
Comment comment = commetns.get(3); // მესამე კომენტარი

მაშინ გაჩნდება კითხვა: როგორ უნდა გაიგოს Hibernate-მა, რომელი ელემენტია მესამე, ყველა ელემენტის მეხსიერებაში ჩატვირთვის გარეშე?

ამ პრობლემის გადაჭრისთვის გთავაზობენ comment ცხრილში დამატებითი სვეტის გაკეთებას, რომელიც შეინახავს კომენტარის რიგით ნომერს კოლექციაში. ამისთვის საჭიროა სპეციალური ანოტაცია — @OrderColumn.

აი, როგორ გამოიყურება ეს გადაწყვეტილება:


@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-ის მთავარი უპირატესობა

ყველაზე ძლიერი უპირატესობა LazyCollectionOption.EXTRA-ის ჩვენ ვხედავთ, როცა მას ვუთითებთ ანოტაციაში @ManyToMany. ვუბრუნდებით ჩვენს ძველ შემთხვევას, როცა გვყავს Employee, Task, და შესაძლებელია მრავალი ამოცანის დანიშვნა ერთ მომხმარებელზე.

ჩვენი Java-კლასები ამ შემთხვევაში ასე გამოიყურება:

კლასი Employee:


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

და კლასი EmployeeTask:


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

და დირექტორისთვის დავალების დასამატებლად, საჭიროა დაახლოებით ასეთი კოდი:


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

აი, თუ Task კლასში employees ველის აქვს ანოტაცია LazyCollectionOption.EXTRA, მაშინ employees (Task კლასის) და task (Employee კლასის) კოლექციები საერთოდ არ ჩაიტვირთება ბაზიდან არცერთხელ.

ამ კოდის შესრულების შემდეგ მხოლოდ ერთი ჩანაწერი ჩაირთვება სერვისულ ცხრილში employee_task, რომელიც, როგორც გახსოვს, დაახლოებით ასე გამოიყურება:

ცხრილი employee_task:
employee_id task_id
1 1
2 2
5 3
5 4
5 5
4 7
6 8
4 101

მწვანე ფერით მონიშნულია დამატებული სტრიქონი. ამ სტრიქონის დასამატებლად, არ არის საჭირო კოლექციების ჩატვირთვა ბაზიდან, — Hibernate ამას შეძლებს ამის გარეშე. ეს არის სწორედ ის შემთხვევა, როდესაც LazyCollectionOption.EXTRA ძალიან აჩქარებს სამუშაოს ბაზასთან.

N+1 პრობლემა

მაგრამ, რა თქმა უნდა, ამ რეჟიმს აქვს უკუმხარეც. ასე, LazyCollectionOption.EXTRA ანოტაციამ შეიძლება გამოიწვიოს N+1 Problem.

თუ გადაწყვეტ მოიარო ყველა კომენტარი შენი მომხმარებლისთვის:


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

მაშინ Hibernate შეასრულებს ცალკე მოთხოვნას თითოეული Comment ობიექტისთვის. ასევე კიდევ ერთ დამატებით მოთხოვნას, რომ მიიღოს ყველა კომენტარის რაოდენობა. ეს შეიძლება მნიშვნელოვნად დაამძიმოს კოდის მუშაობა.

თუ შენი მომხმარებლის 1000 კომენტარი აქვს, მაშინ ამ კოდის შესასრულებლად Hibernate 1001 შეკითხვას შეასრულებს ბაზაში, თუმცა შეეძლო მხოლოდ ერთით. თუ заранее იცოდა, რომ შენ ყველა ამ კლასის სუბიექტი დაგჭირდება.

Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ