2011-03-24 161 views
3

我有多對一的關係,比方說用戶有一個公司。公司實體沒有任何其他關係。休眠二級緩存問題

如果我爲公司的findAll hibernate查詢啓用第二級緩存,第二次重新加載頁面(這意味着用戶已加載,然後還加載了所有公司的列表),我爲每個現有公司選擇select(select。 ..在公司的地方id =?)在休眠輸出。 爲公司調用的findAll發生這種情況時,它看起來像這樣(這是在課堂上一般方法,該方法被擴展爲適當的類型):

return (List<T>) getHibernateTemplate().execute(new HibernateCallback() { 

      public Object doInHibernate(Session session) 
        throws HibernateException, SQLException { 
       Criteria c = session.createCriteria(persistentClass); 
       c.setCacheable(cacheFindAll); 

       return c.list(); 
      } 
     }); 

我只讀策略使用JBoss TreeCacheProvider。如果我使用setCacheable(false),則沒有「不需要」的選擇。

爲什麼會發生這種情況,我該如何消除這種行爲?

回答

6

呼叫setCacheable()是用於使查詢緩存,看到javadoc

Enable caching of this query result, provided query caching is enabled for the underlying session

什麼情況是,這些公司的ID緩存而不是對象本身。如果啓用二級緩存,則這些單獨的公司查詢將由二級緩存處理。

爲了啓用二級緩存,您需要在persistence.xml中設置hibernate.cache.use_second_level_cache = true。此外,您還需要註釋您是否喜歡在二級緩存中緩存的關係和實體。

@OneToMany 
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_ONLY) 
private List<Company> companies; 

和實體緩存:

@Entity 
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_ONLY) 
public class Company { 
    ... 
} 

BTW二級緩存只會緩存關係和實體您發現ID。查詢不能被第二級緩存緩存,並且會一直訪問數據庫(或查詢緩存)。

+0

謝謝,是的,你是正確的setCacheable設置查詢緩存。但我仍然不明白爲什麼有多個選擇發生。它們只有在setCacheable(true)和二級緩存設置爲只讀時纔會發生,當我將它設置爲transactional時,它不會發生。我也以讀寫的方式嘗試了EHcache,但它不會發生。另外,有沒有辦法緩存我需要加載所有的實體? (如國家列表等) – kane77 2011-03-24 23:05:59

+0

如果您執行EntityManager.createQuery(「from Company」)。getResultList();你將擁有你所有的公司在你的二級緩存中。那麼如果你確定你已經完成了與公司惰性加載的所有關係,並且你沒有在查詢中引用公司,那麼他們將總是從二級緩存中讀取(也就是說,如果你不讓緩存過期或溢出)。 – Kdeveloper 2011-03-24 23:35:11