关于hibernate缓存存储

时间:2015-12-13 02:14:27

标签: hibernate caching

众所周知,hibernate有L1和L2缓存。现在我对他们的商店有一些疑问:

  1. 如果启用了L2缓存且L1和L2缓存中没有命中,则hibernate将查询DB。但是,从DB获取结果后,它会将结果仅存储在L2缓存中,还是存储在L1和L2或其他任何内容中?
  2. 如果启用了L2缓存并且一个会话的L1有结果但L2没有,那么休眠会将这个结果从L1复制到L2吗?
  3. 如果L2缓存启用且L2有结果但L1没有,那么休眠会将它从L2复制到L1吗?
  4. 更新

    4。如果我有下一个代码,没有L2缓存和查询缓存:

    List<Student> persons = session.createQuery("from Student").list();
    
    List<Student> students = session.createQuery("from Student").list();
    

    为什么hibernate会查询DB两次?它没有L1缓存,那么它只是第一次查询DB吗?

    提前致谢!

1 个答案:

答案 0 :(得分:0)

  

如果启用了L2缓存且L1和L2缓存中没有命中,则hibernate将查询DB。但是,从DB获取结果后,它会将结果仅存储在L2缓存中,还是存储在L1和L2中还是其他任何内容?

这完全取决于您尝试执行的操作类型

  1. EntityManager.find()

    在这种情况下,只要实体配置了@Cachable并且启用了L2缓存,您从这些查找中收到的任何结果都将在L1和L2中缓存,并将基于您保存在L2中二级缓存配置。

  2. EntityManager.createQuery()

    在这种情况下,它不仅取决于实体是否配置了@Cachable并且启用了L2缓存,还取决于是否通过配置全局启用查询缓存属性hibernate.cache.use_query_cache=true或者是否指定在运行时通过query.setCachable(true)可以缓存特定查询。

    如果查询未被缓存且后续会话运行相同的查询,则不会查询L2缓存,因为查询事先不知道哪些实体标识符映射到执行查询,因此数据源必须是通过SQL查询进行咨询。

  3.   

    如果启用了L2缓存并且一个会话的L1有结果但L2没有,那么休眠会将此结果从L1复制到L2吗?

    见上面的答案。

    如果您执行了entityManager.find(),那么如果它是一个可缓存的实体实例,则L2将使用您刚查询的实体的属性数据进行补充。

    如果您执行entityManager.createQuery(),这将取决于是否启用了查询缓存。如果未启用,则不会将任何数据复制到L2。如果启用了查询缓存,则L2将相应地更新,如上所示。

      

    如果L2缓存启用且L2有结果但L1没有,那么休眠会将它从L2复制到L1吗?

    L1高速缓存将始终具有附加实体的活动状态,无论状态是从L2高速缓存,数据存储区还是两者的组合中提取。

      

    如果我有2&#34; session.createQuery(..)。list()&#34;在一个会话中,为什么hibernate将查询DB两次? Doens有L1缓存,然后是第二个&#34; session.createQuery(...)。list()&#34;应该从L1获得结果吗?

    我将假设两个查询都执行相同的HQL语句,因为这是查询缓存适用于此用例的要求。

    仅仅因为Hibernate在查询期间向数据库发出查询并不意味着不会查询或使用L2缓存。

    首先,是否使用setCachable(true)启用查询缓存的查询?

    假设查询缓存和实体缓存在执行第一个list()时为空,则hibernate会相应地填充实体和查询缓存。在第二次查询期间,它会查询L2缓存,只要实体或查询缓存都没有过期,它就会从L2中重新水合。

    重要的是要注意,如果查询缓存在实体缓存结果后到期,这可能会产生一些性能瓶颈问题,因为L2查询缓存将指示要包含哪些实体,hibernate会发现它们已过期并且将会通过id重新发出每个过期实体的数据库查询。