2010-05-27 171 views
2

我只是想辦法休眠。有點困惑。新手休眠一級緩存混淆

我只是想觀察一級緩存的操作,我理解這種操作是爲了在查詢結束之前對查詢進行批量處理。

但如果我創建了一個對象,休眠立即將其保存,這樣,當我後來在同一事務中更新它,它必須做一個更新過:

Session session = factory.getCurrentSession(); 
session.beginTransaction(); 

Test1 test1 = new Test1(); 
test1.setName("Test 1"); 
test1.setValue(10); 
// Touch it 
session.save(test1); 

System.out.println("At checkpoint 1"); 

test1.setValue(20); 

session.getTransaction().commit(); 

我看到SQL進行保存,然後'在檢查點1',然後是更新的SQL。我有沒有設置錯誤或者我誤解了hibernate的第一級緩存?在第一級緩存中是否有很好的文檔 - 我沒有在休眠文檔中找到任何內容,但我很容易就錯過了。

謝謝!

+0

啊 - 太棒了!謝謝 - 解決了它爲什麼立即保存它的問題。我把它從生成中改爲自己並提供了id,現在兩個sql語句都在最後執行。 我仍然有點困惑,爲什麼有兩個sql語句,如果我提供的ID。我會認爲hibernate可以使用對象中的CURRENT值運行插入,而不是原始值。那麼就不需要做插入和更新。但也許這是要問很多?是否有關於在這些情況下hibernate做什麼和不做的文檔,或者我應該只看代碼? – Jeremy 2010-05-27 14:42:35

+0

也許他們擔心你的數據庫包含一個觸發器,它在插入時執行某些操作並在更新時執行其他操作。在那種情況下,緩存更新會改變行爲? – Cobusve 2010-05-27 15:04:31

+0

謝謝Cobusve--很可能。雖然我也看到,通過對同一對象進行多次更新(記住在每次更新之間調用SaveOrUpdate),只有對象的最終狀態更新到數據庫 - 這意味着任何中間觸發器 - 例如更新歷史記錄表所做的更新 - 不會被解僱,所以也許他們並不擔心觸發器;-) – Jeremy 2010-05-27 15:50:30

回答

2

對於你的問題的第一個版本,你的文件的章節10.2. Making objects persistent中找到一些答案:

新實例化的一個 持久化類被認爲是 瞬間由Hibernate的實例。我們可以通過 做出 瞬態的實例持久化它與會話關聯:

DomesticCat fritz = new DomesticCat(); 
fritz.setColor(Color.GINGER); 
fritz.setSex('M'); 
fritz.setName("Fritz"); 
Long generatedId = (Long) sess.save(fritz); 

如果Cat有一個生成的標識,產生 標識符和分配給catsave()是 調用。如果Cat具有指定的 標識符或組合鍵,則在調用 save()之前應將 標識符分配給 cat實例。您還可以使用persist() 而不是save(),而在EJB3早期版本 草稿中定義了 語義。

  • persist()使暫時實例持久化。但是,它不確保標識符 值將立即分配給 持久實例, 分配可能發生在刷新時間。 persist()還保證,如果在事務 邊界之外調用它, 將不會執行INSERT語句 。在 延長會話/持久性上下文的長時間運行對話中,這是非常有用的。
  • save()確實會返回一個標識符。 如果INSERT必須 執行以獲得標識符(例如 「身份」產生,而不是「序列」),如果你是內部或事務之外 這INSERT立即發生, 不管。在與延長的會話/持久性上下文的長時間對話中,這是有問題的 。

順便說一句,如果你在save()方法仔細觀察,你會發現,它確實返回Serializable(指定的標識符)。


現在,關於你的問題的更新版本,Hibernate的使用一個ActionQueue持有DML排隊的操作作爲會話的事務,後寫語義的一部分。 DML操作在這裏排隊,直到刷新強制它們在數據庫上執行爲止。

當你調用save()persist(),包含要插入的實體的值的副本的插入動作被添加到「插入」名單。

然後,修改的持久化實體,並在沖洗時間,實體被檢測爲髒和其他操作(一個更新動作)添加爲同一實體,該實體的價值觀的另一個副本:待定插入操作不會更新爲新值。

這導致兩個DML操作(INSERTUPDATE)。

此行爲在HHH-2588的評論中有所解釋。它(當然)不是最優的,但是這是當前Hibernate實現的工作方式,我不知道所有的細節來解釋爲什麼Hibernate不執行這種優化(我想這不是那麼簡單)。但隨時提交補丁:)

+0

帕斯卡爾,非常感謝你的全面和明確的答案。我不知道你在哪裏找到這樣的noob問題的耐心,但我非常感謝它:-) – Jeremy 2010-05-27 18:13:30

+0

@Bruce不客氣。實際上,IMO並不是一個簡單的問題,我覺得它非常有趣(許多人甚至沒有嘗試去理解你現在這樣做的事情)。 – 2010-05-27 20:43:27