1.1 ความเป็นมาของปัญหา

เมื่อคุณเริ่มทำงานกับฐานข้อมูลจริง คุณจะจำวลีที่ว่า “การเพิ่มประสิทธิภาพก่อนเวลาอันควรเป็นรากเหง้าของความชั่วร้ายทั้งหมด” ตอนนี้คุณจำเธอในทางลบเท่านั้น เมื่อทำงานกับฐานข้อมูล การเพิ่มประสิทธิภาพเป็นสิ่งที่ขาดไม่ได้ และคุณต้องทำงานกับมันในขั้นตอนการออกแบบ

ไฮเบอร์เนตทำให้การทำงานกับฐานข้อมูลสะดวกมาก คุณสามารถรับออบเจกต์ย่อยใดๆ ได้ง่ายๆ เพียงแค่ใส่คำอธิบายประกอบอย่างถูกต้อง@OneToManyและ @ManyToManyตัวอย่าง:


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

และการได้รับความคิดเห็นของผู้ใช้นั้นง่ายเพียงใด:


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

และคุณจะต้องประหลาดใจอย่างมาก ผู้ใช้มีความคิดเห็นหลายพันรายการ หากคุณเขียนโค้ดแบบนี้ แน่นอนว่า Hibernate จะโหลดความคิดเห็นทั้งหมดของผู้ใช้ แต่มันจะช้ามาก ความคิดเห็นจะใช้หน่วยความจำมาก เป็นต้น

นั่นเป็นเหตุผลที่คุณไม่สามารถเขียนแบบนั้นได้! ในทางทฤษฎีใช่ แต่ในทางปฏิบัติไม่ใช่

1.2 ทำให้สิ่งต่าง ๆ แย่ลงด้วยคอลเลกชัน

ปัญหาก็ยิ่งน่าสนใจ ท้ายที่สุดแล้ว คุณไม่ต้องการความคิดเห็นทั้งหมดของผู้ใช้ แม้ว่าคุณจะแสดงไว้ที่ใดที่หนึ่งบนไคลเอนต์ คุณก็ต้องการแสดงในส่วน - หน้า

ดังนั้นคุณต้องมีวิธีการดังนี้:


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

วิธีแรกส่งคืนความคิดเห็นเพียงหน้าเดียว - 50 ชิ้น วิธีที่สองส่งคืนจำนวนหน้าของความคิดเห็น และนี่คือสิ่งที่เลวร้ายที่สุด เพื่อที่จะค้นหาจำนวนความคิดเห็น คุณต้องดาวน์โหลดความคิดเห็นทั้งหมดจากฐานข้อมูล!

1.3 แสงสว่างที่ปลายอุโมงค์

ดังนั้นจึงไม่มีใครใช้คอลเลกชันลูกที่ยอดเยี่ยมของเรา ไม่ แน่นอนว่าใช้ แต่เป็นส่วนหนึ่งของการสืบค้น HQL เท่านั้น ตัวอย่างเช่น:


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.setParametr("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.setParametr("id", userId);
           	return Math.ceil(query.singleResult()/PAGE_SIZE);
     }
 
}

ข่าวดีก็คือ เราสามารถใช้วิธีการของเราในลักษณะที่เราไม่ต้องโหลดข้อมูลเพิ่มเติมจากฐานข้อมูล ข่าวร้ายก็คือ มันไม่ง่ายเลยที่จะทำงานกับคอลเลกชันของเรา