1.1 Latar belakang masalah

Apabila anda mula bekerja dengan pangkalan data sebenar, anda akan segera mengingati frasa "Pengoptimuman pramatang adalah punca segala kejahatan." Hanya sekarang anda mengingatinya secara negatif. Apabila bekerja dengan pangkalan data, pengoptimuman amat diperlukan. Dan anda perlu bekerja dengannya sudah pada peringkat reka bentuk.

Hibernate menjadikan kerja dengan pangkalan data sangat mudah. Anda boleh mendapatkan sebarang objek kanak-kanak dengan mudah hanya dengan membuat anotasi @OneToManydan @ManyToMany. Contoh:


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

Dan betapa mudahnya untuk mendapatkan komen pengguna:


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

Dan anda akan mendapat kejutan besar. Pengguna mempunyai beberapa ribu komen. Jika anda menulis kod seperti ini, Hibernate sudah tentu akan memuatkan semua komen pengguna. Tetapi ia akan menjadi sangat perlahan, komen akan mengambil banyak memori dan sebagainya.

Itulah sebabnya anda tidak boleh menulis seperti itu! Secara teori, ya, tetapi dalam praktiknya, tidak.

1.2 Memburukkan keadaan dengan koleksi

Masalahnya lebih menarik. Lagipun, biasanya anda tidak memerlukan semua komen pengguna. Walaupun anda memaparkannya di suatu tempat pada klien, anda lebih suka melakukannya dalam bahagian - halaman.

Jadi anda memerlukan kaedah seperti ini:


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

Kaedah pertama mengembalikan hanya satu halaman komen - 50 keping. Kaedah kedua mengembalikan bilangan halaman komen. Dan ini adalah yang paling teruk. Untuk mengetahui bilangan komen, anda perlu memuat turun semua komen daripada pangkalan data!

1.3 Cahaya di hujung terowong

Oleh itu, tiada siapa yang menggunakan koleksi kanak-kanak kami yang hebat. Tidak, sudah tentu ia digunakan, tetapi hanya sebagai sebahagian daripada pertanyaan HQL. Contohnya seperti ini:


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

Berita baiknya ialah kami boleh melaksanakan kaedah kami sedemikian rupa sehingga kami tidak perlu memuatkan data tambahan daripada pangkalan data. Berita buruknya ialah bukan mudah untuk bekerja dengan koleksi kami.