EhCache Hibernate二级缓存maxBytesLocalHeap缓慢
我在Spring驱动的应用程序中使用Hibernate(4.2.15.Final)和EhCache(2.6.9)作为二级缓存设置了一个非常标准的持久层设置。
一切都按预期工作。 但是,将条目放入二级缓存有时需要很长时间。
我已经在一个显式的ehcache.xml
文件中配置了我的域模型类的缓存(我没有配置默认缓存):
...
我在持久化上下文启动时记录了以下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
注释来限制图形的行走,但我不确定如何解决这个问题:
- 我是否必须忽略双向关联的一方以避免循环?
- 我是否必须明确忽略我的域模型类的瞬态成员?
- 一般来说,将EhCache与Hibernate一起使用时使用
maxBytesLocalHeap
是否明智,还是应该选择maxEntriesLocalHeap
,因为Hibernate为每个实体保留了一个单独的缓存区域?
[更新] :我发现,临时成员不会被Hibernate缓存(参见Hibernate:是否可以在二级缓存中保存瞬态字段? ),所以不管怎么说它们都不应该被ehcache看待。 正确?
简短的回答
事实certificate,我遇到的问题是在我的模型中使用Joda-Time实例的结果(我使用Jadira的UserType库来映射Joda类型)。
Joda类型保留了各种内部引用(包括对时间顺序信息的引用,从而产生巨大的对象图),Ehcache的SizeOfEngine
这些引用,导致我的原始警告。
我发现如何配置SizeOfEngine引擎以排除这些引用没有干净的方法,但是我想再一个更简洁的方法是强制Hibernate只将相关信息放到二级缓存中(我的一个时间实例) LocalDateTimes
情况)。
更新
Jadira在实现自定义类型时选择不好:请在此处查看我的答案
更多细节
这是我发现的关于我的OP(使用Hibernate 4.2.15.Final,EhCache 2.6.9和UserType 3.2.0.GA):
首先,我对Hibernate如何在其二级缓存中存储实体产生了误解。 在阅读Lorimer关于真正理解二级和查询缓存的博客文章之后,很多事情对我来说更有意义:
- 您不必担心双向关联(或者关于此问题的循环图),因为Hibernate只会将关联的ID放入缓存中。 即使它将整个实体的引用放入缓存中 – 它没有 – 但EhCache的SizeOf引擎将跟踪已访问过的图形中的对象,并且不会对它们进行两次调整。
- 同样,您不必担心瞬态字段,因为Hibernate不会将它们放入缓存中
- 理论上,使用
maxBytesLocalHeap
配置不应该有任何问题。 当您使用EhCache的SizeOf引擎无法正确测量的自定义用户类型时,会出现问题。
我知道这是一个老问题。 但它可能对某些人有用。 我有同样的警告。 我花了很多时间来解决这个问题。 在我的例子中,EhCache不会忽略所有的hibernate代理类。 我的实体有一些具有惰性关联的字段,在测量大小期间,EhCache遍历整个hibernate图。
最后我找到了这个页面并解决了它。