2016-12-27 103 views
0

我有一個Java/Spring應用程序與數據庫實體。 其中一個實體是DataSet。每個DataSet可以有一個父節點DataSet。 並且父母 - DataSet有多個(OneToMany)子女。休眠集合緩存

@OneToMany(fetch=FetchType.LAZY) 
    @IndexColumn(name = "order_id") 
    @JoinColumn(name = "parent_dst_id") 
    @Fetch(FetchMode.SELECT) 
    @Cache(usage = org.hibernate.annotations.CacheConcurrencyStrategy.READ_WRITE) 
    public List<DataSet> getChildren() 
    { 
     return children; 
    } 

經過幾年很多在某些父數據集進行分組的數據集。

parentDataset.getChildren().size() // > 200.000 

在代碼(我不知道這是正確的方式)增加一個新的數據集(調查)與母體時,以下行執行:

surveyDataset.setParent(parentDataset); 
parentDataset.getChildren().add(surveyDataset); 

直到最近children根本沒有被緩存。第二條語句導致數據庫中的長時間運行查詢。

現在我們最近添加了datasets.children到緩存。這樣,一切都變得非常快。

直到...

..一個孩子,數據集添加(同一母公司下進行!)再次變得很慢(即:它開始再次查詢該數據庫)。

我認爲緩存正在被驅逐或清除或者其他什麼,這就是再次查詢的原因。

參見:http://planet.jboss.org/post/collection_caching_in_the_hibernate_second_level_cacheTLDR: 「Hibernate並不在緩存更新集合,它只是刪除它。」)

我試圖理解日誌(net.sf.ehcache = DEBUG和org.hibernate.SQL = DEBUG)但那很困難。

所以我只能和我有什麼做的,以防止再次加載所有兒童的數據集(在新數據集中的所有兄弟姐妹)有幾個問題

1)? 2)如何調試我的緩存中發生了什麼?它驅逐父母嗎?還是所有的孩子?正如文章中所解釋的那樣,它可能會重新加載整個集合。

回答

0
  1. 您可以將cache usage =「read-write」更改爲cache usage =「read-only」,然後在代碼中維護驅逐策略。這是管理緩存的最安全方式,但需要在管理緩存的代碼中進行相當多的調整。

  2. 調試有2種方法。

    1. 在hibernate中啓用show_sql並查看查詢是否執行了兩次,這通常表明hibernate試圖首先檢查緩存,找不到併發送第二個查詢數據庫的方式。
    2. 日誌高速緩存命中率在這篇文章中所解釋的:http://winterbe.com/posts/2009/10/01/how-to-log-hibernate-cache-this/
+0

謝謝! 「維持驅逐政策」究竟意味着什麼? – codesmith

+0

當你把緩存用法=「讀寫」時,hibernate處理對象驅逐。只要使用session.save/update更新任何對象,它就會從緩存中逐出緩存的對象。但是Read不允許hibernate這樣做,所以你將不得不以編程方式在代碼中寫入緩存逐出來處理它。 – user1622369