Loại tìm nạp mặc định cho một-một, nhiều-một và một-nhiều trong Hibernate


103

Loại tìm nạp mặc định trong ánh xạ ngủ đông là gì?

Những gì tôi biết sau khi khám phá là:

  • đối với một đối một, nó rất háo hức .
  • đối với một-nhiều, nó là lười biếng .

Nhưng sau khi thử nghiệm nó trong Eclipse, tất cả đều háo hức.

Nó phụ thuộc vào việc tôi đang sử dụng JPA hay Hibernate?


1
Trong trường hợp bạn vẫn tham gia vào các chủ đề JPA - tôi đã cập nhật câu hỏi của bạn bằng một câu trả lời mới, vì các câu trả lời cũ đã lỗi thời cho phiên bản Hibernate hiện tại.
Alexander Rühl

Câu trả lời:


193

Nó phụ thuộc vào việc bạn đang sử dụng JPA hay Hibernate.

Từ thông số JPA 2.0 , các giá trị mặc định là:

OneToMany: LAZY
ManyToOne: EAGER
ManyToMany: LAZY
OneToOne: EAGER

Và trong chế độ ngủ đông, tất cả là Lười

CẬP NHẬT:

Phiên bản mới nhất của Hibernate phù hợp với các mặc định JPA ở trên.


11
"And in hibernate, all is Lazy" rõ ràng nó đã thay đổi trong các phiên bản gần đây. Hãy xem câu trả lời của Alexander Rühl bên dưới .
Dinei

1
Hibernate là một trong những triển khai JPA, do đó khi bạn đang sử dụng Hibernate, bạn đang sử dụng JPA :)
xenteros

Đây là một truy vấn phổ biến. @Ashish Agarwal Bạn có thể vui lòng cập nhật dòng cuối cùng của câu trả lời của bạn. Trong Hibernate nó không phải là Lazy cho tất cả bây giờ.
Saurabh Tiwari,

Đã cập nhật bài đăng liên quan đến hành vi Ngủ đông mới nhất.
M Anouti, 27/09/18

Có một bản cập nhật, tuyên bố rằng háo hức là kiểu tìm nạp mặc định cho mọi ánh xạ, được chương 11.3 từ chối trong cả tài liệu Hibernate 5.x hiện tại và 6.x mới, vì vậy tôi đã hoàn tác chỉnh sửa. Bên cạnh đó, không nên có sự háo hức tự động, vì điều này có nghĩa là có thể chọn toàn bộ cơ sở dữ liệu khi tìm nạp một đối tượng.
Alexander Rühl

51

Tôi biết câu trả lời là chính xác tại thời điểm đặt câu hỏi - nhưng vì mọi người (như tôi phút này) vẫn tình cờ thấy họ tự hỏi tại sao WildFly 10 của họ hoạt động khác, tôi muốn cập nhật cho Hibernate 5 hiện tại Phiên bản .x:

Trong Hướng dẫn sử dụng Hibernate 5.2, nó được nêu trong chương 11.2. Áp dụng các chiến lược tìm nạp :

Đề xuất Hibernate là đánh dấu tĩnh tất cả các liên kết là lười biếng và sử dụng các chiến lược tìm nạp động cho sự háo hức. Thật không may, điều này trái ngược với đặc tả JPA định nghĩa rằng tất cả các liên kết một-một và nhiều-một nên được tìm nạp một cách háo hức theo mặc định . Hibernate, với tư cách là nhà cung cấp JPA, tôn trọng mặc định đó.

Vì vậy, Hibernate cũng hoạt động như Ashish Agarwal đã nêu ở trên cho JPA:

OneToMany: LAZY
ManyToOne: EAGER
ManyToMany: LAZY
OneToOne: EAGER

(xem Thông số JPA 2.1 )


Và điều gì sẽ xảy ra nếu chúng ta sử dụng chế độ ngủ đông gốc thay vì JPA impl, nó có hoạt động theo cùng một cách không?
jMounir

@jMounir: Chà, tôi chưa thử, nhưng vì Hibernate nói rằng nó hoạt động giống như được định nghĩa trong JPA, nên tôi không hiểu tại sao điều đó lại khác khi sử dụng Hibernate cho chính nó. Trong cả hai trường hợp, người ta có thể ghi đè chiến lược mặc định.
Alexander Rühl

15

Để trả lời câu hỏi của bạn, Hibernate là một triển khai của tiêu chuẩn JPA. Hibernate có các vấn đề hoạt động riêng nhưng theo tài liệu Hibernate

Theo mặc định, Hibernate sử dụng tìm nạp lựa chọn lười biếng cho các bộ sưu tập và tìm nạp proxy lười biếng cho các liên kết có giá trị đơn. Các giá trị mặc định này có ý nghĩa đối với hầu hết các liên kết trong phần lớn các ứng dụng.

Vì vậy, Hibernate sẽ luôn tải bất kỳ đối tượng nào bằng chiến lược tìm nạp lười biếng, bất kể bạn đã khai báo kiểu quan hệ nào. Nó sẽ sử dụng một proxy lười biếng (phải được khởi tạo nhưng không phải là rỗng) cho một đối tượng trong mối quan hệ một-một hoặc nhiều-một và một tập hợp rỗng mà nó sẽ hydrat hóa các giá trị khi bạn cố gắng truy cập nó .

Cần hiểu rằng Hibernate sẽ chỉ cố gắng điền các giá trị vào các đối tượng này khi bạn cố gắng truy cập đối tượng, trừ khi bạn chỉ định fetchType.EAGER.


0

Đối với các liên kết có giá trị đơn, tức là Một-một và Nhiều-một: -
Mặc định Lazy = proxy Tải
chậm proxy : - Điều này ngụ ý một đối tượng proxy của thực thể liên kết của bạn được tải. Điều này có nghĩa là chỉ id kết nối hai thực thể được tải cho đối tượng proxy của thực thể được liên kết.
Vd: A và B là hai thực thể có liên kết Nhiều thành một. nghĩa là: Có thể có nhiều A cho mọi B. Mọi đối tượng của A sẽ chứa một tham chiếu của B.
'

public class A{
    int aid;
    //some other A parameters;
    B b;
}
public class B{
    int bid;
     //some other B parameters;
}

`
Quan hệ A sẽ chứa các cột (viện trợ, giá thầu, ... các cột khác của thực thể A).
Quan hệ B sẽ chứa các cột (giá thầu, ... các cột khác của thực thể B)

Proxy ngụ ý khi A được tìm nạp, chỉ id được tìm nạp cho B và được lưu trữ vào một đối tượng proxy của B mà chỉ chứa id. Đối tượng proxy của B là đối tượng của lớp proxy là lớp con của B chỉ có các trường tối thiểu. Vì giá thầu đã là một phần của quan hệ A, nên không cần thiết phải kích hoạt truy vấn để nhận giá thầu từ quan hệ B. Các thuộc tính khác của thực thể B chỉ được tải một cách chậm rãi khi một trường không phải giá thầu được truy cập.

Đối với Bộ sưu tập, tức là Nhiều-Nhiều và Một-Nhiều: -
Mặc định Lazy = true


Cũng xin lưu ý rằng chiến lược tìm nạp (chọn, tham gia, v.v.) có thể ghi đè lười. nghĩa là: Nếu lazy = 'true' và fetch = 'join', tìm nạp A cũng sẽ lấy B hoặc Bs (Trong trường hợp tập hợp). Bạn có thể hiểu được lý do nếu bạn nghĩ về nó.
Tìm nạp mặc định cho một liên kết có giá trị là "tham gia".
Tìm nạp mặc định cho các bộ sưu tập là "chọn". Vui lòng xác minh hai dòng cuối cùng. Tôi đã suy luận điều đó một cách hợp lý.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.