我在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
是否明智,或者我应该选择maxEntriesLocalHeap
,因为Hibernate无论如何都要为每个实体保留一个单独的缓存区域? [更新] :我发现,Hibernate不会缓存瞬态成员(请参阅Hibernate: Is it possible to save a transient field in second level cache?),因此无论如何都不应该将它们视为ehcache。正确?
答案 0 :(得分:3)
简短回答
事实证明,我遇到的问题是在我的模型中使用Joda-Time实例的结果(我使用Jadira's UserType library来映射Joda类型)。
Joda类型保留了各种内部引用(包括对时间顺序信息的引用,从而产生了一个巨大的对象图),Ehcache的SizeOfEngine
遍历这些引用,导致我的原始警告。
我发现如何配置SizeOfEngine引擎以排除这些引用没有干净的方法,但是我想再一个更简洁的方法是强制Hibernate只将相关信息放入二级缓存中(一次)在LocalDateTimes
}的情况下的实例。
<强>更新强>
Jadira在实施自定义类型时选择不当:请参阅my answer here
更多详情
以下是我发现的OP(使用Hibernate 4.2.15.Final,EhCache 2.6.9和UserType 3.2.0.GA):
首先,我对Hibernate如何将实体存储在其二级缓存中存在误解。在阅读Lorimer关于Truly Understanding the Second-Level and Query Caches的博客文章之后,很多事情对我来说更有意义:
maxBytesLocalHeap
配置不应该出现任何问题。当您使用EhCache的SizeOf引擎无法正确测量的自定义用户类型时,会出现问题。答案 1 :(得分:1)
我知道这是一个老问题。但它可能对某些人有用。 我有同样的警告。我花了很多时间来解决这个问题。 在我的例子中,EhCache不会忽略所有的hibernate代理类。我的实体有一些具有惰性关联的字段,在测量大小期间,EhCache遍历整个休眠图。
最后我找到了this page并解决了它。