1.1 Latar belakang masalah

Saat Anda mulai bekerja dengan basis data nyata, Anda akan segera mengingat frasa "Optimalisasi dini adalah akar dari segala kejahatan". Hanya sekarang Anda mengingatnya secara negatif. Saat bekerja dengan database, pengoptimalan sangat diperlukan. Dan Anda harus mengerjakannya pada tahap desain.

Hibernasi membuat bekerja dengan database menjadi sangat nyaman. Anda dapat dengan mudah mendapatkan objek anak apa pun hanya dengan memberi 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 mendapatkan komentar pengguna:


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

Dan Anda akan mendapat kejutan besar. Pengguna memiliki beberapa ribu komentar. Jika Anda menulis kode seperti ini, Hibernasi tentu saja akan memuat semua komentar pengguna. Tapi itu akan sangat lambat, komentar akan memakan banyak memori dan sebagainya.

Itu sebabnya Anda tidak bisa menulis seperti itu! Secara teori, ya, tetapi dalam praktiknya, tidak.

1.2 Memperburuk keadaan dengan koleksi

Masalahnya bahkan lebih menarik. Lagi pula, biasanya Anda tidak pernah membutuhkan semua komentar pengguna. Bahkan jika Anda menampilkannya di suatu tempat di klien, Anda lebih suka melakukannya di bagian - halaman.

Jadi, Anda memerlukan metode 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);
   }
 
}

Metode pertama hanya mengembalikan satu halaman komentar - 50 buah. Metode kedua mengembalikan jumlah halaman komentar. Dan ini yang terburuk. Untuk mengetahui jumlah komentar, Anda harus mengunduh semua komentar dari database!

1.3 Cahaya di ujung terowongan

Oleh karena itu, tidak ada yang menggunakan koleksi anak kami yang luar biasa. Tidak, tentu saja digunakan, tetapi hanya sebagai bagian dari kueri HQL. Misalnya 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);
     }
 
}

Kabar baiknya adalah kita dapat mengimplementasikan metode kita sedemikian rupa sehingga kita tidak perlu memuat data tambahan dari database. Berita buruknya adalah tidak mudah bekerja dengan koleksi kami.