Hibernate FetchType là gì? Phân biệt FetchType Lazy với Eager

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:

Hibernate FetchType là gì? Phân biệt FetchType Lazy với Eager

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ượng Company từ database thì nó sẽ không lấy các đối tượng Employee liên quan
  • fetch = FetchType.EAGER tức là khi bạn find, select đối tượng Company từ database thì tất cả các đối tượng Employee liên quan sẽ được lấy ra và lưu vào listEmployee

* 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 method company.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ượng Employee liên quan và lưu vào listEmployee, và khi kết thúc transaction listEmployee 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 transaction listEmployee sẽ không có đối tượng employee nào
  • fetch = FetchType.EAGER thì khi lấy đối tượng Company là nó mặc định query luôn các đối tượng Employee liên quan và lưu vào listEmployee, do đó khi kết thúc transaction, listEmployee sẽ có chứa các đối tượng Employee của Company đó.

FetchType mặc định

  • Với annotation @ManyToOne @OneToOne thì fetchType mặc định là EAGER
  • Với annotation @ManyToMany@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

stackjava.com