Mengenali LazyCollectionOption.EXTRA

Tetapi yang paling menarik ialah nilai LazyCollectionOption.EXTRA. Jika anda menentukannya sebagai nilai anotasi @LazyCollection , maka Hibernate akan menangguhkan pemuatan elemen koleksi selama mungkin.

Jika anda cuba mendapatkan bilangan elemen dalam koleksi:

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

Kemudian untuk semua kod ini, Hibernate akan melaksanakan hanya satu pertanyaan:

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

Walau bagaimanapun, jika anda ingin mendapatkan satu komen daripada koleksi, contohnya nombor 3:

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

Kemudian persoalan timbul: bagaimana Hibernate sepatutnya mengetahui bahawa elemen itu adalah yang ketiga tanpa memuatkan semua elemen ke dalam ingatan?

Untuk menyelesaikan masalah ini, adalah dicadangkan untuk membuat lajur tambahan dalam jadual ulasan, yang akan menyimpan nombor ordinal ulasan dalam koleksi ulasan. Dan juga untuk ini anda memerlukan anotasi khas - @OrderColumn .

Begini rupa penyelesaian itu:

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

Kelebihan utama LazyCollectionOption.EXTRA

Kami melihat kelebihan terkuat LazyCollectionOption.EXTRA apabila kami menentukannya dengan anotasi @ManyToMany . Mari kita ambil kes lama kita di mana kita mempunyai Pekerja, Tugas, dan kita boleh menetapkan banyak tugas kepada satu pengguna.

Kelas Java kami kelihatan seperti ini:

Kelas pekerja :

@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 menambah tugas kepada pengarah, anda perlu menulis sesuatu seperti kod 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 medan pekerja dalam kelas Tugas mempunyai anotasi LazyCollectionOption.EXTRA, maka koleksi pekerja (kelas Tugas) dan koleksi tugas (kelas Pekerja) tidak akan dimuatkan daripada pangkalan data sama sekali .

Apabila kod ini dilaksanakan, hanya satu rekod akan dimasukkan ke dalam jadual perkhidmatan employee_task, yang, seperti yang anda ingat, kelihatan seperti ini:

jadual tugas_pekerja :
ID pekerja id_tugas
1 1
2 2
5 3
5 4
5 5
4 7
6 8
4 101

Garis tambahan diserlahkan dengan warna hijau. Untuk menambah baris ini, anda tidak perlu memuatkan koleksi daripada pangkalan data - Hibernate akan melakukannya tanpanya. Ini betul-betul berlaku apabila LazyCollectionOption.EXTRA sangat mempercepatkan kerja dengan pangkalan data.

Masalah N+1

Tetapi, sudah tentu, mod ini juga mempunyai kelemahan. Contohnya, anotasi LazyCollectionOption.EXTRA menjana Masalah N+1 .

Jika anda memutuskan untuk membaca semua ulasan 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 melaksanakan permintaan berasingan untuk setiap objek Komen. Dan juga satu lagi pertanyaan tambahan untuk mendapatkan kiraan semua ulasan. Ini boleh memperlahankan kod dengan ketara.

Jika pengguna anda mempunyai 1000 ulasan, maka Hibernate akan membuat 1001 pertanyaan kepada pangkalan data untuk melaksanakan kod ini, walaupun ia boleh dilakukan dengan satu. Jika anda tahu terlebih dahulu bahawa anda memerlukan semua objek kelas ini.