Mengenal LazyCollectionOption.EXTRA

Namun yang paling menarik adalah nilai LazyCollectionOption.EXTRA. Jika Anda menetapkannya sebagai nilai anotasi @LazyCollection , maka Hibernasi akan menunda pemuatan elemen koleksi selama mungkin.

Jika Anda mencoba mendapatkan jumlah elemen dalam koleksi:

User user = session.load(User.class, 1);
List<Comment> comments = user.getComments();
int count = commetns.size();

Kemudian untuk semua kode ini, Hibernate hanya akan menjalankan satu kueri:

SELECT COUNT(id) FROM comment WHERE user_id = 1;

Namun, jika Anda ingin mendapatkan satu komentar dari koleksi, misalnya nomor 3:

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

Kemudian muncul pertanyaan: bagaimana seharusnya Hibernate mengetahui bahwa elemen tersebut adalah yang ketiga tanpa memuat semua elemen ke dalam memori?

Untuk mengatasi masalah ini, diusulkan untuk membuat kolom tambahan di tabel komentar, yang akan menyimpan nomor urut komentar dalam kumpulan komentar. Dan juga untuk ini Anda memerlukan anotasi khusus - @OrderColumn .

Seperti inilah solusinya:

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

Keunggulan utama LazyCollectionOption.EXTRA

Kami melihat keuntungan terkuat dari LazyCollectionOption.EXTRA saat kami menetapkannya dengan anotasi @ManyToMany . Mari ambil kasus lama kita di mana kita memiliki Karyawan, Tugas, dan kita dapat menetapkan banyak tugas ke satu pengguna.

Kelas Java kami terlihat seperti ini:

Kelas karyawan :

@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>();

}

Dan kelas 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>();

}

Dan untuk menambahkan tugas ke direktur, Anda perlu menulis sesuatu seperti kode ini:

Employee director = session.find(Employee.class, 4);
EmployeeTask task = session.find(EmployeeTask.class, 101);
task.employees.add(director);

session.update(task);
session.flush();

Jadi, jika bidang karyawan di kelas Tugas memiliki anotasi LazyCollectionOption.EXTRA, maka kumpulan karyawan (dari kelas Tugas) dan kumpulan tugas (dari kelas Karyawan) tidak akan pernah dimuat dari database sama sekali .

Saat kode ini dijalankan, hanya satu catatan yang akan dimasukkan ke dalam tabel layanan employee_task, yang, seperti yang Anda ingat, terlihat seperti ini:

tabel employee_task :
identitas pegawai task_id
1 1
2 2
5 3
5 4
5 5
4 7
6 8
4 101

Baris yang ditambahkan disorot dengan warna hijau. Untuk menambahkan baris ini, Anda tidak perlu memuat koleksi dari database - Hibernate akan melakukannya tanpa itu. Inilah yang terjadi ketika LazyCollectionOption.EXTRA sangat mempercepat pekerjaan dengan database.

Masalah N+1

Namun tentunya mode ini juga memiliki kekurangan. Misalnya, anotasi LazyCollectionOption.EXTRA menghasilkan Masalah N+1 .

Jika Anda memutuskan untuk memeriksa semua komentar pengguna Anda:

User user = session.load(User.class, 1);
List<Comment> comments = user.getComments();
for (Comment comment : comments) {
    System.out.println(comment);
}

Kemudian Hibernate akan mengeksekusi permintaan terpisah untuk setiap objek Comment. Dan juga satu permintaan tambahan lagi untuk menghitung semua komentar. Ini secara signifikan dapat memperlambat kode.

Jika pengguna Anda memiliki 1000 komentar, maka Hibernate akan membuat 1001 kueri ke database untuk mengeksekusi kode ini, meskipun bisa dilakukan dengan satu. Jika Anda tahu sebelumnya bahwa Anda akan membutuhkan semua objek kelas ini.