[Hibernate] Sự khác nhau giữa session.get() và session.load()

Thường xuyên, ta sẽ thấy các Hibernate developer sử dụng kết hợp session.get() và session load(). Bạn có tự hỏi những điểm khác nhau giữa chúng và khi nào nên sử dụng 1 trong 2?


Sự khác nhau giữa session.get() và session.load()
Thực ra, cả 2 hàm được sử dụng để lấy ra 1đối tượng với cơ chế khác nhau, tất cả sẽ được trình bay bên dưới.


1. session.load()
  • Nó thường trả về một “proxy” (1 thuật ngữ của hibernate) mà không cần hit tại database. Trong Hibernate, proxy là 1 đối tượng với giá trị identifier đã cho, property của nó chưa được khởi tạo, nó chỉ giống như một đối tượng giả tạm thời.
  • Nếu không tìm thấy dữ liệu phù hợp, nó sẽ ném ra exception ObjectNotFoundException.


2. session.get()
  • Nó hit database và trả về một đối tượng thật, và đối tượng này đại diện dòng trong cơ sở dữ liệu, không phải poxy.
  • Nếu không tìm thấy dòng nào, nó sẽ trả về null.

Về performance
Hibernate tạo ra mọi thứ vì một số lý do, khi sử dụng association, nó thường lấy 1 đối tượng (persistent instance) từ cơ sở dữ liệu và gán nó làm tham chiếu cho đối tượng khác, chỉ để duy trì mối quan hệ. Thử vài ví dụ để hiểu trong tình huống nào bạn nên sử dụng session.load().


1. session.get()
Ví dụ, trong Stock application, Stock và StockTransactions có mối quan hệ “one-to-many”, khi muốn lưu 1 stock transaction, thường khai báo giống dưới đây.

Java:
Stock stock = (Stock)session.get(Stock.class, new Integer(2));
           StockTransaction stockTransactions = new StockTransaction();
           //set stockTransactions detail
           stockTransactions.setStock(stock);
           session.save(stockTransactions);
Kết quả
Code:
Hibernate:
    select ... from mkyong.stock stock0_
    where stock0_.STOCK_ID=?
Hibernate:
    insert into mkyong.stock_transaction (...)
    values (?, ?, ?, ?, ?, ?)
Trong session.get(), Hibernate sẽ hit database để lấy ra đối tượng Stock và sử nó làm tài nguyên tham chiếu cho StockTransaction. Tuy nhiên, xử lý insert này là liên tục, ở đây có thể có hàng trăm hoặc hàng nghìn giao dịch trong nữa giờ, điều này có cần thiết để hit vào database để lấy đối tượng Stock vói đầy đủ mọi thông tin để insert 1 stock transaction không? Sau tất cả, chỉ cần Id Stock làm tài nguyên tham chiếu cho StockTransaction là đủ.


2. session.load()
Với kịch bản bên trên, session.load() sẽ là giải pháp tốt, hãy xem ví dụ bên dưới:

Java:
Stock stock = (Stock)session.load(Stock.class, new Integer(2));
           StockTransaction stockTransactions = new StockTransaction();
           //set stockTransactions detail
           stockTransactions.setStock(stock);
           session.save(stockTransactions);
Kết quả
Code:
Hibernate:
    insert into mkyong.stock_transaction (...)
    values (?, ?, ?, ?, ?, ?)
Trong session.load(), Hibernate sẽ không hit database (không có lệnh select nào ở kết quả) để lấy ra đối tượng Stock, nó sẽ trả về một đối tượng Stock proxy - một đối tượng giả với giá trị định danh đã cho. Trong trường hợp này, một đối tượng proxy là đủ để lưu một stock transaction.


Exception
Trường hơp xảy ra exception

session.load()
Java:
Stock stock = (Stock)session.load(Stock.class, new Integer(100)); //proxy

 //initialize proxy, no row for id 100, throw ObjectNotFoundException
System.out.println(stock.getStockCode());
Nó trả về một đối tượng proxy với giá trị identity đã cho, thậm chí giá trị này không tồn tại trong database. Tuy nhiên, khi khởi tạo proxy để lấy ra các property của nó từ database. nó sẽ hit vào database với lệnh select. Nếu không tìm thấy dòng nào, exception ObjectNotFoundException sẽ được ném ra.

Code:
org.hibernate.ObjectNotFoundException: No row with the given identifier exists:
[com.mkyong.common.Stock#100]

session.get()
Java:
//return null if not found
Stock stock = (Stock)session.get(Stock.class, new Integer(100));
System.out.println(stock.getStockCode()); //java.lang.NullPointerException
Nó sẽ trả về null, nếu giá trị identity không được tồn tại.


Kết luận
Không có giải pháp luôn luôn đúng, bạn phải hiểu sự khác biệt ở giữa chúng và quyết định xem cái nào là phù hợp nhất trong project của mình.


Cám ơn các bạn đã theo dõi. Hẹn gặp lại các bạn trong các bài viết sau :D

Bài viết tham khảo tại: https://mkyong.com/hibernate/different-between-session-get-and-session-load/
 

Bình luận