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图。

最后我找到了这个页面并解决了它。