2013-02-20 101 views
8

我們在我們的項目中使用hibernate4ehcache。我們主要研究不可變的對象,所以緩存是一個非常適合我們應用的功能。嘗試啓用查詢緩存,我們遇到了以下問題:Hibernate緩存:緩存查詢返回的對象是否存儲在L2緩存中?

假設我們有以下的實體:

@Entity 
@Table(name = "DOGS") 
@Immutable 
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY) 
class Dog { 
    @Id @Column 
    Long id; 
    @Column 
    String name; 
} 

和查詢:

Criteria criteria = session.createCriteria(Dog.class); 
criteria.add(Restrictions.in("id", ids)); 
criteria.setCacheable(true); 

查詢緩存傳輸TimeToLive設置爲約3/4的狗timeToLive。這裏的情景(請糾正我,如果我犯了一個錯誤的假設):

  1. 第一次查詢稱爲(假設緩存爲空),它是執行和返回的狗實例存儲在第二級緩存。另外,Dog ID保存在查詢緩存中。
  2. 第二次調用查詢(Dog ID位於查詢緩存中,Dog對象位於L2緩存中)時,一切正常。查詢緩存返回id,Dog從L2中獲取。
  3. 當查詢緩存過期(但L2緩存仍然有效)時,查詢將重新運行並緩存Dog ID。
  4. 現在二級緩存過期,Dog對象和所有對象都從緩存中逐出。查詢緩存仍然具有緩存的ids,因此hibernate會一個一個獲取Dog對象,這需要永久。

第三個問題是糾纏我。查詢緩存在數據庫中失效並重新運行,獲取Dog對象,但Dog對象未在L2緩存中更新。它看起來像查詢只更新查詢緩存中的狗標識符,而不是二級緩存。

有沒有辦法強制查詢更新L2緩存?也許這種情況需要以不同的方式處理?

+0

您可以啓用讀/寫入緩存模式,以便EHCache在更新時處理它。 – Phani 2013-07-24 17:21:22

+0

該實體是隻讀的,所以這不會有幫助。 – 2013-07-25 10:08:53

回答

1

我嘗試這樣做,在過去的工作對我來說,清潔L2緩存

//clear the cache entity 
sf.getCache().evictEntity(Dog.class,12345); //Entity with 12345 id 

//or clear a collection 
sf.getCache().evictCollection("com.package.Dog.getCol",12345); //Collections 
//Note: the collection contains the name of the fully qualified class. 

//then, run the query 

希望它可以幫助

+0

你什麼時候建議我應該清理緩存?如果我在每次請求之前清除它,根本沒有任何意義。 – 2013-07-25 10:28:35

+0

我對計劃事件做了乾淨的緩存(由於項目事實)。 所以不時(預定的時間來自系統團隊)我們清理緩存 – victoriza 2013-07-25 11:01:44

+0

因此,這取決於您的項目數據庫大小和使用情況。如果沒有準確的數據,猜測是不可能的 – victoriza 2013-07-25 11:02:57

2

見二級緩存爲對象/ POJO的你指定越來越緩存。但是查詢緩存是爲特定查詢創建的。因此,當你的查詢緩存被更新時,兩者都是不相關的,二級緩存不會更新,這似乎很自然。這就是爲什麼它們都有不同的配置。您可以參考Hibernate Documentationthis linkthis link可能會幫助您瞭解事情。

+0

我知道這些是兩個不同的緩存,但查詢緩存使用域緩存通過ID檢索對象,對不對?這導致了所描述的問題,到目前爲止我還沒有找到任何解決方案。 – 2013-07-25 19:26:08

+0

因此,這個答案不能解決所描述的問題。 – 2013-07-26 09:23:12

+0

朋友你需要接受這個設計。這不是問題,這是爲此設計的。 – 2013-07-26 09:32:20

0

在我的情況下,我禁用休眠中的最小put設置,然後查詢緩存將在每次發佈SQL時自動更新所有相關的二級緩存。

我認爲這是解決你的問題「以強制查詢也更新L2緩存」(這也來煩我很長一段時間......)

<property name="hibernate.cache.use_minimal_puts" value="false"/>