Hibernate FetchType là gì? Phân biệt FetchType Lazy với Eager.
(Xem thêm: Hướng dẫn tự học Hibernate)
(Xem thêm: Code ví dụ Hibernate FetchType = EAGER (Eager loading))
(Xem thêm: Code ví dụ Hibernate FetchType = LAZY (Lazy loading))
Hibernate FetchType là gì?
Trong Hibernate, FetchType là một thuộc tính trong các annotation @OneToOne, @OneToMany, @ManyToOne, @ManyToMany, được dùng để định nghĩa phương thức lấy các đối tượng liên quan.
Ví dụ mình có quan hệ sau:
Quan hệ giữa company và employee là một-nhiều.
Khi mapping sang class với Hibernate sẽ như sau:
@Entity
@Table(name = "company")
public class Company {
//...
@OneToMany(fetch = FetchType.LAZY, mappedBy = "company")
private List<Employee> listEmployee = new ArrayList<>();
}
Annotation @OneToMany định nghĩa quan hệ giữa company và employee là 1-n. Trong đó có thuộc tính fetch:
fetch = FetchType.LAZYtức là khi bạn find, select đối tượngCompanytừ database thì nó sẽ không lấy các đối tượngEmployeeliên quanfetch = FetchType.EAGERtức là khi bạn find, select đối tượngCompanytừ database thì tất cả các đối tượngEmployeeliên quan sẽ được lấy ra và lưu vàolistEmployee
* Lưu ý:
fetch = FetchType.LAZYtức là mặc định không lấy ra các đối tượng liên quan nhưng bên trong transaction, bạn gọi methodcompany.getListEmployee()thì nó vẫn có dữ liệu nhé, bởi vì khi bạn gọi method nó sẽ query các đối tượngEmployeeliên quan và lưu vàolistEmployee, và khi kết thúc transactionlistEmployeesẽ chứa các employee liên quan. Tuy nhiên nếu bạn không gọi method đó thìlistEmployeekhông có dữ liệu và khi kết thúc transactionlistEmployeesẽ không có đối tượng employee nàofetch = FetchType.EAGERthì khi lấy đối tượngCompanylà nó mặc định query luôn các đối tượngEmployeeliên quan và lưu vàolistEmployee, do đó khi kết thúc transaction,listEmployeesẽ có chứa các đối tượngEmployeecủaCompanyđó.
FetchType mặc định
- Với annotation
@ManyToOnevà@OneToOnethì fetchType mặc định làEAGER - Với annotation
@ManyToManyvà@OneToManythì fetchType mặc định làLAZY
Có sự khác nhau như trên là vì với annotation @ManyToOne, và @OneToOne thì khi select với fetchType = EAGER nó chỉ lấy ra nhiều nhất 1 đối tượng liên quan nên không ảnh hưởng gì tới performance. Còn nếu sử dụng fetchType = EAGER với @ManyToMany, @OneToMany thì có thể nó lấy ra rất nhiều đối tượng liên quan dẫn tới làm giảm hiệu năng, tốn bộ nhớ.
Ưu nhược điểm của mỗi loại FetchType
Với FetchType = LAZY(Lazy Loading):
- Ưu điểm: tiết kiệm thời gian và bộ nhớ khi select
- Nhược điểm: gây ra lỗi
LazyInitializationException, khi muốn lấy các đối tượng liên quan phải mở transaction 1 lần nữa để query
Với FetchType = EAGER(Eager Loading):
- Ưu điểm: có thể lấy luôn các đối tượng liên quan, xử lý đơn giản, tiện lợi
- Nhược điểm: tốn nhiều thời gian và bộ nhớ khi select, dữ liệu lấy ra bị thừa, không cần thiết.
Okay, Done!
References:
https://docs.jboss.org/hibernate/jpa/2.1/api/javax/persistence/FetchType.html