2010-09-13 114 views
10

我已經將實體加載到我的事務中並更改了該實體的屬性。該交易尚未提交。現在我想獲得更改屬性的原始值。強制Hibernate查詢訪問數據庫

我試着用一個HQL查詢,如select p.property from Person p where p.id = 1以及事務中加載的實體的ID。

我在執行查詢之前設置了query.setHint("org.hibernate.cacheMode", CacheMode.IGNORE);。但沒有成功。 Hibernate返回當前事務中設置的值,而不是數據庫中的值。

有沒有辦法解決這個問題?

+0

難道你最終的問題是,Hibernate抱怨兩次會話中的同一實體嗎?聽起來你可能想重新審視實現。 – 2010-09-14 03:16:48

回答

11

我已經加載了一個實體到我的交易中並且已經改變了該實體的一個屬性。該交易尚未提交。現在我想獲得更改屬性的原始值。

總之:自己追蹤舊價值。

我已經嘗試過使用HQL查詢,如從Person p中選擇p.property,其中p.id = 1與事務中加載的實體的ID一起使用。

Hibernate將一個實體的唯一版本加載到給定數據庫標識符的會話(第一級緩存)中。這不起作用。

我已經設置了query.setHint(「org.hibernate.cacheMode」,CacheMode.IGNORE);在執行查詢之前。

這個提示是用來影響查詢緩存(依賴於二級高速緩存),這會不會影響你現在的「問題」。

有沒有辦法解決這個問題?

要麼

  • 使用session.refresh()強迫你的實體的重載(你會鬆散的變化)
  • 店作爲開頭提到的前值。
  • 調用在另一個事務中執行查詢的服務。
2

這可能會幫助:

如果要強制查詢緩存 刷新其地區 之一(忽略任何緩存的結果發現 有),可以使用 爲org.hibernate.Query .setCacheMode(CacheMode.REFRESH)。 結合您爲給定查詢定義的區域, Hibernate將有選擇地強制在該特定 區域中緩存的 結果被刷新。這在 底層數據可能已被通過一個單獨的過程更新 例 特別有用,並且是經由 org.hibernate.SessionFactory.evictQueries遠 更有效的替代區域的散裝 驅逐()。

(從http://docs.jboss.org/hibernate/stable/core/reference/en/html/performance.html,第20.4.2節)。

但是,是否打算在其他進程更新數據庫時使用,並且應謹慎使用。 你的情況是不同的。由於此方法發生在任何事務之外,因此您應確保它不與您的設計衝突。也許你可以重構你的呼叫流程,以避免這種行爲,並從其他來源檢索字段或緩存中的修改發生之前...

+0

回顧我的回答我發現它沒有完全解決您的問題。即使您完全禁用二級緩存,您的實體數據可能會進入一級緩存(會話)。爲此,您應該刷新或驅逐對象...但是您應該重新輸入您想要在事務提交中保存的字段。 – Sebastian 2010-09-13 13:47:06

1

要做到這一點的唯一方法是運行查詢以外的當前交易。

7

StatelessSession爲我工作。

StatelessSession statelessSession = sessionFactory.openStatelessSession(); 
try { 
    return statelessSession.get(Ticket.class, ticketKey, LockMode.READ) 
} finally { 
    statelessSession.close() 
}