Lazy Loading

All lectures for UZ purposes
Daraja, Dars
Mavjud

1.1 Muammoning tarixiy asoslari

Haqiqiy ma'lumotlar bazalari bilan ishlashni boshlaganingizda, “Erta optimallashtirish – barcha yomonliklarning ildizi” degan so'zni eslaysiz. Lekin bu so'zni salbiy nuqtai nazardan eslaysiz. Ma'lumotlar bazasi bilan optimallashtirishsiz ishlashning iloji yo'q. Va bu bilan ishlash loyihalash bosqichida qilish kerak.

Hibernate ma'lumotlar bazasi bilan ishlashni juda qulay qiladi. To'g'ri @OneToMany va @ManyToMany annotatsiyalarini qo'yish orqali siz istalgan farzand obyektlarni osongina olishingiz mumkin. Masalan:


@Entity @Table(name="user")
class User {
   @Column(name="id")
   public Integer id;
 
   @OneToMany(cascade = CascadeType.ALL) @JoinColumn(name = "user_id")
   public List<Comment> comments;
}

Va foydalanuvchining sharhlarini olish qanchalik oson:


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

Va bu yerda sizni katta syurpriz kutmoqda. Foydalanuvchining bir necha ming sharhlari mavjud. Agar siz shunday kod yozsangiz, Hibernate albatta foydalanuvchining barcha sharhlarini yuklaydi. Ammo bu juda sekin bo'ladi, sharhlar ko'p xotira oladi va hokazo.

Shuning uchun bunday yozish mumkin emas! Nazariyada – mumkin, amaliyotda esa – yo'q.

1.2 Kolleksiyalar bilan vaziyatni og'irlashtiramiz

Muammo yanada qiziqarliroq. Chunki odatda sizga foydalanuvchining barcha sharhlari kerak bo'lmaydi. Hatto siz ularni biror joyda mijozda ko'rsatsangiz ham, buni qismlarga – sahifalarga ajratgan holda qilishni ma'qul ko'rasiz.

Shuning uchun sizga quyidagi kabi metodlar kerak:


public class CommentsManager {
    private static final PAGE_SIZE = 50;
 
    public List<Comment> getCommentsPage(int userId, int pageIndex){
     	User user = session.get(User.class, userId);
     	List<Comment> comments = user.getComments();
     	return comments.subList(pageIndex * PAGE_SIZE, PAGE_SIZE);
    }
 
   public int getCommentsPageCount(int userId)   {
     	User user = session.get(User.class, userId);
     	List<Comment> comments = user.getComments();
     	return Math.ceil(  comments.size()/PAGE_SIZE);
   }
 
}

Birinchi metod faqat bir sahifa sharhlarini – 50 donasini qaytaradi. Ikkinchi metod sharhlar sahifalarining sonini qaytaradi. Va bu eng dahshatli narsa. Faqat sharhlar sonini bilish uchun siz bazadan barcha sharhlarni yuklashingiz kerak edi!

1.3 Tunnel oxiridagi yorug'lik

Shunday qilib, bizning ajoyib farzand kolleksiyalarimiz hech kim tomonidan ishlatilmaydi. Yo'q, albatta, ularni ishlatishadi, lekin faqat HQL-so'rovlarning bir qismi sifatida. Masalan, shunday:


public class CommentsManager {
      private static final PAGE_SIZE = 50;
 
       public List<Comment> getCommentsPage(int userId, int pageIndex){
           	String hql = "select comments from User where id = :id";
           	Query<Comment> query = session.createQuery( hql, Comment.class);
           	query.setParameter("id", userId);
           	query.setOffset(pageIndex * PAGE_SIZE);
           	query.setLimit(PAGE_SIZE);
           	return query.list();
      }
 
      public int getCommentsPageCount(int userId)   {
           	String hql = "select count(comments) from User where id = :id";
           	Query<Integer> query = session.createQuery( hql, Integer.class);
           	query.setParameter("id", userId);
           	return Math.ceil(query.singleResult()/PAGE_SIZE);
     }
 
}

Yaxshi xabar – biz metodlarimizni bazadan ortiqcha ma'lumotlarni yuklamaslik uchun shunday amalga oshirishimiz mumkin. Yomon xabar – bizning kolleksiyalar bilan bunday oddiy ishlashning imkoni yo'q.

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