LazyCollectionOption.EXTRA

All lectures for KK purposes
Деңгей , Сабақ
Қол жетімді

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;

Алайда егер сен коллекциядан үшінші комментарий алғың келсе:


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 аннотациясына ие болса, онда Task класының employees коллекциясы және Employee класының task коллекциясы базадан ешқашан жүктелмейді.

Бұл код орындалған кезде тек бір ғана жазба 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 Мәселесін туындатады.

Егер сен қолданушының барлық комментарийлерін қарағың келсе:


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 сұрау жасайды, бірақ бір сұраумен шектелуі мүмкін еді. Егер ол алдын ала осы кластың барлық объектілері қажет болатынын білсе.

Пікірлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION