2009-03-04 33 views
83

Từ API, tôi có thể thấy nó có liên quan đến proxy. Nhưng tôi không thể tìm thấy nhiều thông tin về proxy và không hiểu sự khác biệt giữa việc gọi số session.getsession.load. Ai đó có thể vui lòng giải thích hoặc hướng dẫn tôi đến trang tham chiếu không?Hibernate: Sự khác biệt giữa session.get và session.load

Cảm ơn bạn !!

Trả lời

111

Từ Hibernate forum:

này từ cuốn sách Hibernate trong hành động. Tốt một đọc ..


Lấy đối tượng bằng cách nhận dạng sau Đoạn mã Hibernate lấy một đối tượng người dùng từ cơ sở dữ liệu:

User user = (User) session.get(User.class, userID); 

Các get() phương pháp là đặc biệt bởi vì các định danh xác định duy nhất một cá thể đơn lẻ của một lớp. Do đó, các ứng dụng sử dụng mã định danh là một đối tượng liên tục để xử lý một đối tượng liên tục là một đối tượng cố định với số . Truy xuất bằng số nhận dạng có thể sử dụng bộ nhớ cache khi truy xuất một đối tượng, tránh cơ sở dữ liệu bị truy cập nếu đối tượng đã được lưu trong bộ nhớ cache. Hibernate cũng cung cấp phương thức load():

User user = (User) session.load(User.class, userID); 

Phương thức load() cũ hơn; get() được thêm vào API của Hibernate do người dùng yêu cầu . Sự khác biệt là tầm thường:

Nếu tải() không thể tìm thấy đối tượng trong bộ nhớ cache hoặc cơ sở dữ liệu, ngoại lệ là được ném. Phương thức load() không bao giờ trả về null. Phương thức get() trả về nếu không tìm thấy đối tượng.

Phương thức load() có thể trả về proxy thay vì một thực thể liên tục thực. Proxy là trình giữ chỗ kích hoạt tải đối tượng thực khi lần đầu tiên được truy cập ; Trên tay khác, get() không bao giờ trả về proxy. Lựa chọn giữa get() và load() rất dễ dàng: Nếu bạn chắc chắn đối tượng liên tục là tồn tại và không tồn tại sẽ không được coi là ngoại lệ, thì tải() là một tùy chọn tốt là . Nếu bạn không chắc chắn có một trường hợp liên tục với mã định danh nhất định, hãy sử dụng get() và kiểm tra giá trị trả lại để xem giá trị đó có phải là không. Sử dụng tải() có một hàm ý thêm: Ứng dụng có thể truy xuất tham chiếu hợp lệ (một proxy) tới một cá thể liên tục mà không cần nhấn cơ sở dữ liệu để truy lục trạng thái liên tục của nó. Vì vậy, tải() có thể không ném ngoại lệ khi nó không tìm thấy đối tượng liên tục trong bộ nhớ cache hoặc cơ sở dữ liệu; ngoại lệ sẽ được ném sau, khi proxy được truy cập. Tất nhiên, việc truy xuất đối tượng theo số nhận dạng không linh hoạt như sử dụng các truy vấn tùy ý.

+1

Tôi đang gỡ lỗi một vấn đề ngay bây giờ trong đó phiên.Get () đang trả về proxy! –

+7

Cảm ơn rất nhiều! Phần tiền cho tôi là: "Nếu tải() không thể tìm thấy đối tượng trong bộ nhớ cache hoặc cơ sở dữ liệu, ngoại lệ được ném. Phương thức get() trả về null nếu không tìm thấy đối tượng". – Chris

+15

JavaDoc cho Session.get nói: Trả về thể hiện dai dẳng của lớp thực thể đã cho với số nhận dạng đã cho, hoặc null nếu không có cá thể liên tục như vậy. (Nếu cá thể, hoặc một proxy cho cá thể, đã được liên kết với phiên, trả về cá thể hoặc proxy đó.) Vì vậy, phần từ cuốn sách nói: "Mặt khác, get() không bao giờ trả về một proxy." không đúng. – Vicky

14

Vâng, ít nhất, trong phiên làm việc (id) sẽ tải đối tượng từ cơ sở dữ liệu, trong khi session.Load (id) chỉ tạo đối tượng proxy cho nó mà không cần rời khỏi máy chủ của bạn. Hoạt động giống như mọi thuộc tính lười biếng khác trong POCO của bạn (hoặc POJOs :). Sau đó, bạn có thể sử dụng proxy này làm tham chiếu đến chính đối tượng đó để tạo mối quan hệ, v.v.

Hãy nghĩ đến việc có một đối tượng chỉ giữ Id và sẽ tải phần còn lại nếu bạn cần. Nếu bạn chỉ cần chuyển nó xung quanh để tạo ra các mối quan hệ (như FKs), id là tất cả những gì bạn cần.

+0

vì vậy bạn muốn nói load (id) trước tiên sẽ nhấn vào cơ sở dữ liệu để kiểm tra xem nó là id hợp lệ hay không và hơn sẽ trả về đối tượng proxy và khi các thuộc tính của đối tượng này được truy cập nó truy cập lại cơ sở dữ liệu? nó không phải là một kịch bản không? hai truy vấn để tải đối tượng đơn lẻ? – faisalbhagat

+0

Không, tải (id) sẽ không xác nhận hợp lệ id vì vậy không có chuyến đi khứ hồi tới DB. Chỉ sử dụng nó khi bạn chắc chắn rằng bạn chắc chắn nó hợp lệ. –

9

session.load() sẽ luôn trả về "proxy" (cụm từ Hibernate) mà không cần nhấn cơ sở dữ liệu. Trong Hibernate, proxy là một đối tượng có giá trị định danh đã cho, các thuộc tính của nó chưa được khởi tạo, nó giống như một đối tượng giả tạm thời. Nếu không tìm thấy hàng nào, nó sẽ ném ra một ObjectNotFoundException.

session.get() luôn nhấn cơ sở dữ liệu và trả về đối tượng thực, đối tượng đại diện cho hàng cơ sở dữ liệu chứ không phải proxy. Nếu không tìm thấy hàng nào, nó sẽ trả về giá trị rỗng.

Hiệu suất với các phương pháp này cũng tạo sự khác biệt. giữa hai ...

0

Ngoài ra, chúng ta phải cẩn thận khi sử dụng tải vì nó sẽ ném một ngoại lệ nếu đối tượng không có mặt. Chúng ta phải sử dụng nó chỉ khi chúng ta chắc chắn rằng đối tượng tồn tại.

1

Một hậu quả gián tiếp của việc sử dụng "tải" thay vì "nhận" là khóa lạc quan bằng cách sử dụng thuộc tính phiên bản có thể không hoạt động như bạn mong đợi. Nếu tải chỉ đơn giản là tạo proxy và không đọc từ cơ sở dữ liệu, thuộc tính phiên bản sẽ không được tải. Phiên bản sẽ chỉ được tải khi/nếu sau đó bạn tham chiếu đến thuộc tính trên đối tượng, hãy kích hoạt lựa chọn. Trong khi đó, một phiên khác có thể cập nhật đối tượng và phiên của bạn sẽ không có phiên bản gốc mà nó cần thực hiện kiểm tra khóa lạc quan - vì vậy cập nhật phiên của bạn sẽ ghi đè cập nhật của phiên khác mà không có cảnh báo.

Đây là một nỗ lực để phác thảo ra kịch bản này với hai phiên làm việc với một đối tượng có cùng số nhận dạng. Phiên bản ban đầu cho đối tượng trong DB là 10.

Session 1     Session 2 
---------     --------- 
Load object 
Wait a while.. 
          Load object 
          Modify object property 
          [triggers db 'select' - 
          version read as 10] 
          Commit 
          [triggers db update, 
          version modified to 11] 
Modify object property 
    [triggers db 'select' - 
    version read as 11] 
Commit 
    [triggers db update, 
    version modified to 12] 

Chúng tôi thực sự muốn phiên 1 của cam kết thất bại với một ngoại lệ khóa lạc quan, nhưng nó sẽ thành công ở đây.

Sử dụng "get" thay vì "tải" hoạt động xung quanh vấn đề, bởi vì nhận được ngay lập tức sẽ phát hành một lựa chọn, và số phiên bản sẽ được tải vào đúng thời điểm để kiểm tra khóa lạc quan.

2

Một điểm nữa bổ sung ::

get phương thức Hibernate Lớp phiên trả về null nếu đối tượng không được tìm thấy trong bộ nhớ cache cũng như trên cơ sở dữ liệu. trong khi phương thức load() ném ObjectNotFoundException nếu đối tượng không được tìm thấy trên cache cũng như trên cơ sở dữ liệu nhưng không bao giờ trả về null.

0

Giải thích xuất sắc được tìm thấy ở http://www.mkyong.com/hibernate/different-between-session-get-and-session-load
session.load():
Nó sẽ luôn luôn trả về một “proxy” (Hibernate hạn) mà không va vào cơ sở dữ liệu.
Trong Hibernate, proxy là một đối tượng có giá trị định danh đã cho, các thuộc tính của nó chưa được khởi tạo, nó giống như một đối tượng giả tạm thời.
Nó sẽ luôn trả về một đối tượng proxy với giá trị nhận dạng đã cho, ngay cả giá trị danh tính không tồn tại trong cơ sở dữ liệu. Tuy nhiên, khi bạn cố gắng khởi tạo proxy bằng cách truy xuất thuộc tính của nó từ cơ sở dữ liệu, nó sẽ nhấn cơ sở dữ liệu với câu lệnh chọn. Nếu không tìm thấy hàng, một ObjectNotFoundException sẽ ném.
session.get():
Nó luôn luôn nhấn cơ sở dữ liệu (nếu không tìm thấy trong bộ nhớ đệm) và trả về đối tượng thực, một đối tượng đại diện cho hàng cơ sở dữ liệu, chứ không phải proxy.
Nếu không tìm thấy hàng nào, nó sẽ trả về giá trị rỗng.

0

tải() không thể tìm thấy đối tượng từ bộ nhớ cache hoặc cơ sở dữ liệu, ngoại lệ được ném và phương thức load() không bao giờ trả về giá trị rỗng.

phương thức get() trả về null nếu không tìm thấy đối tượng. Phương thức load() có thể trả về một proxy thay vì một thực thể dai dẳng thực tế get() không bao giờ trả về một proxy.