我对在学习 hibernate 缓存教程时发现的语句有疑问。
陈述1:-一级缓存始终与Session对象相关联。 Hibernate 默认使用这个缓存。
问题 1:-
因为此缓存默认保存来自 session 方法(如加载、获取等)的所有结果。是否会因为保存所有对象而成为主要内存问题?
问题 2:-
我们是否需要默认启用此缓存或它在那里?如果需要,我可以禁用一级缓存吗?如果是怎么办?
以下问题适用于一级和二级缓存
问题 3:-
如果我从缓存中获取相同的对象(假设我在同一 session 中两次加载 customerid 为 1 的对象 customer),从缓存返回的两个对象将具有与位于缓存中的对象不同的引用。 对吗?因为如果我更新客户对象中的某些字段,它不应该反射(reflect)在缓存中,除非调用保存/更新方法。
问题4:-
根据我的理解,如果我们尝试从该缓存中第二次从 id 获取客户对象,它将返回相同的旧对象,即使它在两者之间得到了更新。 我们如何确保它在更新时从数据库中读取,否则从缓存中读取?我想我们可以将读写缓存策略与类似 EHCache
问题 5:- 关于查询缓存
我读到这个声明:-查询中的更新经常发生。因此,对于查询缓存,需要两个缓存区域。
用于存储结果。(仅缓存标识符值和值类型的结果)。 用于存储最近的更新。
我认为“查询中的更新经常发生”意味着我们通常会更改一些参数值,例如 select * from customer where custid=?
所以 id
将被更改对于不同的客户 ID。因此查询缓存将保留每个查询(连同参数)和每个查询返回的结果。
对吧?但是不确定为什么我们需要两个缓存区域来进行查询缓存?
最佳答案
据我所知
答案 01:
Hibernate 缓存加载的对象,以避免对数据库进行不必要的访问。避免持久性上下文的最简单方法是使用 StatelessSession
。 Stateless Hibernate Session 没有脏检查责任,因此可以很好地满足您没有一级缓存(持久上下文)的要求。
答案 02:
- 您不必启用一级缓存
回答 03
- 如果一个对象使用其身份在同一 session 中加载两次,Hibernate 确保返回相同的对象,无论是否启用二级缓存。让我澄清一下,二级缓存不缓存对象的实例。它维护实例的序列化(不完全)版本。 以下link简要说明hibernate二级缓存的结构。
很抱歉,我无法理解“更新客户对象但未反射(reflect)在缓存中”背后的概念。我希望该链接能澄清您的问题。
回答 04
- 如果配置不正确,就会出现从缓存中获取过时数据的问题。
如果缓存上的过期时间尚未发生,将获取状态数据。可以使用
Session.evict()
执行驱逐,但是您可能不清楚需要驱逐哪些数据。因此,缓存应该始终是优化数据库访问的最后一步。 通过重新评估集合关系上的关联和获取计划,可以达到良好的优化水平,从而避免 N+1 选择问题,同时避免。
EHCache 为不更新的数据提供读写
缓存策略 符合事务read committed
保护。那就是避免dirty reads但不能帮助反对repeatable reads .
检查 EHCache 配置 here
答案 05:查询缓存
查看这些链接以更好地了解 session 缓存和查询缓存
答:Session Cache
B. Second Level Cache
C. Query CacheCheckout this link其中对查询缓存的结构进行了简要/更简单的解释。
希望这对您有所帮助。
关于hibernate - 关于 Hibernate 缓存机制的一些说明?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7488978/