在我的Spring驱动的应用程序中,我使用Hibernate(4.2.15.Final)和EhCache(2.6.9)作为第二级缓存,在标准的持久层中进行了设置。
一切正常。但是,将条目放入第二级缓存有时会花费一些时间。
我已经在一个显式ehcache.xml
文件中配置了域模型类的缓存(我没有配置默认缓存):
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
name="hibernate"
updateCheck="false"
monitoring="autodetect"
dynamicConfig="false"
maxBytesLocalHeap="300M"
maxBytesLocalDisk="500M">
<cache
name="org.mycorp.model.MyEntity"
eternal="true"
overflowToDisk="false"
diskPersistent="false"
maxBytesLocalHeap="5M" />
...
</ehcache>
在持久性上下文启动时,我收到以下INFO消息记录:
DefaultSizeOfEngine | using Agent sizeof engine
以及执行期间的以下警告
ObjectGraphWalker | The configured limit of 1,000 object references was reached while attempting to calculate the size of the object graph. Severe performance degradation could occur if the sizing operation continues. [...]
AFAIK ObjectGraphWalker
必须调整放入缓存的实体的大小,因为我使用配置了单个缓存区域maxBytesLocalHeap
。
我的领域模型非常复杂,我知道可以通过@IgnoreSizeOf
注释限制图表的移动,但是我不确定如何解决该问题:
maxBytesLocalHeap
将EhCache与Hibernate一起使用是明智的选择还是我应该接受maxEntriesLocalHeap
,因为Hibernate 仍在为每个实体保留一个单独的缓存区域?[更新]:我发现,Hibernate不会缓存临时成员,所以无论如何ehcache都不应考虑它们。正确?
简短答案
原来,我遇到的问题是由于在模型中使用了Joda-
Time实例(我使用Jadira的UserType库来映射Joda类型)。
Joda类型保留了各种内部引用(包括对导致年代久远的对象图的年代信息的引用),而Ehcache遍历SizeOfEngine
这些引用导致了我的原始警告。
我没有找到一种干净的方法来配置SizeOfEngine引擎以排除这些引用,但是再一次,我猜想一种更干净的方法是强制Hibernate首先仅将相关信息放入第二级缓存(在我的时间实例中的情况LocalDateTimes
)。
更多细节
这是我关于OP的发现(使用Hibernate 4.2.15.Final,EhCache 2.6.9和UserType 3.2.0.GA):
首先,我对Hibernate如何在第二级缓存中存储实体存有误解。阅读Lorimer关于真正了解二级缓存和查询缓存的博客条目后,很多事情对我来说更有意义:
maxBytesLocalHeap
。当前,当您使用EhCache的SizeOf引擎无法正确衡量的自定义用户类型时,会出现问题。问题内容: 一级缓存与hibernate中的查询缓存是否不同?我看过有关第一级和查询缓存的文章,所以我很困惑。 问题答案: 默认情况下,第一级缓存处于启用状态,并且基于每个会话。默认情况下,查询缓存未启用,它在多个会话之间共享,应始终与二级缓存一起使用。 要启用查询缓存,应使用以下属性:
问题内容: 在我的应用程序中,我使用了hibernate-core-4.1.8 jar,并希望将ehCache用作第二级缓存。我当前使用的jar是ehcache- core-2.5.0。我将其放置在WebContetn / WEB-INF / lib文件夹中,并将其放置在类路径中。 我的hibernate.cfg.xml看起来像这样: 放置在JavaResources / src文件夹中的ehca
问题内容: 我正在使用Spring + JPA + Hibernate。我正在尝试启用Hibernate的二级缓存。在我的春天,我有: 运行时出现错误: 所以有人抱怨我没有启用二级缓存。我试图通过添加到我的启用它: 但是仍然没有喜悦。我还尝试将其添加到ehcache.xml中: 但这仍然行不通。将更改为也无济于事: 我的实体类被注释为使用缓存 那么,如何启用二级缓存? 编辑: 这是在bean下:
问题内容: 我知道一个事实,它是 Hibernate 使用的一级缓存,一旦我们从中检索到一个实体,就会从而不是从DB中获取对具有 相同标识符 的 同一实体 的后续get调用,直到is Open 为止。 话虽如此,我对休眠如何将第一级缓存与数据库同步感到怀疑吗?考虑以下情形 所以我的问题是 由于是从一级缓存中提取的,因此有更新的值吗? 如果在会话打开时有人直接更新DB并修改User对象,那么是否与D
问题内容: 我正在使用hibernate处理spring项目,并希望使用ehcache实现二级缓存。我看到了许多解决方法: 引入注释 一个旨在成为继任者的工具集。 可以很好地集成到休眠本身中,以使用例如注释进行缓存。 使用代理。基于注释的配置迅速变得有限或复杂(例如,注释嵌套的多个级别) 就我个人而言,我认为还不够彻底,因此我可能更愿意考虑发展得更为积极。尽管这似乎是最完整的实现(例如,读取和写入
问题内容: 我该如何决定使用哪个? , , , 。 我阅读了https://www.hibernate.org/hib_docs/v3/api/org/hibernate/cache/CacheConcurrencyStrategy.html,但没有足够详细地解释。 问题答案: 在Hibernate文档确实在他们定义了很好的工作: 19.2.2。策略:只读 如果您的应用程序需要读取而不是修改持久类