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.LAZY
tức là khi bạn find, select đối tượngCompany
từ database thì nó sẽ không lấy các đối tượngEmployee
liên quanfetch = FetchType.EAGER
tức là khi bạn find, select đối tượngCompany
từ database thì tất cả các đối tượngEmployee
liên quan sẽ được lấy ra và lưu vàolistEmployee
* Lưu ý:
fetch = FetchType.LAZY
tứ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ượngEmployee
liên quan và lưu vàolistEmployee
, và khi kết thúc transactionlistEmployee
sẽ chứa các employee liên quan. Tuy nhiên nếu bạn không gọi method đó thìlistEmployee
không có dữ liệu và khi kết thúc transactionlistEmployee
sẽ không có đối tượng employee nàofetch = FetchType.EAGER
thì khi lấy đối tượngCompany
là nó mặc định query luôn các đối tượngEmployee
liên quan và lưu vàolistEmployee
, do đó khi kết thúc transaction,listEmployee
sẽ có chứa các đối tượngEmployee
củaCompany
đó.
FetchType mặc định
- Với annotation
@ManyToOne
và@OneToOne
thì fetchType mặc định làEAGER
- Với annotation
@ManyToMany
và@OneToMany
thì 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