2011-03-24 116 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