簡體   English   中英

使用Hibernate一級緩存

[英]Use of Hibernate first level cache

這看起來很簡單。我嘗試了很多但是失敗了。

據我所知,Hibernate一級緩存意味着會話級緩存。當我們在同一個會話中多次檢索同一個對象時,它將從Cache中檢索。

例如,我在數據庫中有一個ID為100的Employee記錄。

我打開一個會話並獲取該員工對象。直到我關閉該對象在同一會話中可用的會話。

問題:為什么我需要在同一個會話中多次檢索同一個對象(在我關閉它之前,它是如何在會話中可用的)?

據我所知,Hibernate一級緩存意味着會話級緩存。當我們在同一個會話中多次檢索同一個對象時,它將從Cache中檢索。

它是半正確的。 除了你所說的,第一級緩存的一個主要原因是,在同一會話下,Hibernate將確保相同的實體(具有相同ID的實體)將由相同的對象實例表示。

只有當您通過ID從會話中獲取實體時,您所說的才是正確的:

Foo foo1 = session.get(Foo.class, 1L);
Foo foo2 = session.get(Foo.class, 1L);

第一次調用get()將轉到DB加載Foo 當調用第二個調用時,Hibernate將檢查在此會話中是否已檢索到任何ID為1的Foo 正如之前檢索過的那樣,Hibernate將簡單地獲取Foo實例並返回給您。

但是,這種情況並不是最常見的情況,您將看到第一級緩存生效。 考慮一下:

// psuedo code only
User user = findByUserName("ADRIAN");  // assume ID = 777
List<User> users = findAllActiveUsers();

(假設上面的查找程序在內部運行查詢通過Hibernate會話)當Hibernate運行第二個查詢時,內部Hibernate運行SQL,獲取結果集,並將每個記錄轉換為用戶。 假設其中一個活動用戶具有ID 777.當Hibernate構造該User對象實例時,它將首先檢查它是否存在於第一級緩存中。 因為它先前已被檢索(在先前的查詢中通過用戶名查找),而不是構造新的User對象實例,Hibernate將簡單地重用先前構建的實例(並存儲在第一級緩存中)並在結果列表中使用它。

通過這樣做,Hibernate可以在同一個會話中確保如果您通過不同的方式檢索相同的實體(具有相同ID的相同類),您可以始終假設該實體將是相同的對象實例。

想想一個更復雜的例子,你試圖從你的系統中檢索Order s,它指的是User (假設是Many-To-One)。 您將發現的是,不同的Order ,每當它引用同一個User (在DB中)時,它實際上是指同一個User對象實例。


對於這個問題

在關閉它之前它是如何在會話中提供的

它更像是Hibernate的內部實現細節。 但是,從概念上講,你可以想象它,每個Session內部都有一個Map,關鍵是Entity Type + ID,值是實體對象實例。

當您從數據庫查詢並且會話為您構建實體時,對於每個實體,它將從地圖中查找它是否已存在。 如果沒有,會話將構造實體並放入地圖。 如果已經存在,則會話將僅使用地圖中的實體

當您通過ID(通過Session.get()Session.load()等獲取實體)時的類似想法

你並不需要從EntityManager的訪問同一對象多次,但如果你這樣做,你會得到相同的對象。 這就是緩存的意義所在。 至於你的第二個問題:EntityManager保留對這個對象的引用,如果再次請求同一個對象,則返回它。

我建議使用像http://docs.oracle.com/javaee/6/tutorial/doc/bnbpz.html這樣的JPA教程。 恕我直言,你應該專注於學習JPA並簡單地將Hibernate視為JPA提供者。

如果后續調用需要檢索此員工對象,則可以從同一會話獲取,而不是從DB獲取

這取決於您如何管理SessionEntityManager 如果是按請求創建的,則無需再次查詢。 但是如果重用Session / EntityManager則可以多次檢索同一個對象,以便從第一級緩存返回。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM