Java EhCache Hibernate二级缓存maxBytesLocalHeap慢速

Java EhCache Hibernate二级缓存maxBytesLocalHeap慢速,java,hibernate,caching,jpa,ehcache,Java,Hibernate,Caching,Jpa,Ehcache,我在Spring驱动的应用程序中使用Hibernate(4.2.15.Final)和EhCache(2.6.9)作为二级缓存,设置了一个非常标准的持久层 一切正常。但是,将条目放入二级缓存有时需要很长时间 我已经在显式ehcache.xml文件中配置了域模型类的缓存(我没有配置默认缓存): 在执行过程中发出以下警告 ObjectGraphWalker | The configured limit of 1,000 object references was reached while attem

我在Spring驱动的应用程序中使用Hibernate(4.2.15.Final)和EhCache(2.6.9)作为二级缓存,设置了一个非常标准的持久层

一切正常。但是,将条目放入二级缓存有时需要很长时间

我已经在显式
ehcache.xml
文件中配置了域模型类的缓存(我没有配置默认缓存):

在执行过程中发出以下警告

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
注释限制图的遍历,但我不确定如何解决这个问题:

  • 我是否必须忽略双向关联的一侧以避免循环
  • 我是否必须显式忽略域模型类的临时成员
  • 一般来说,当与Hibernate一起使用EhCache时,使用
    maxBytesLocalHeap
    明智吗?还是我应该选择
    maxEntriesLocalHeap
    ,因为Hibernate为每个实体保留一个单独的缓存区域

[更新]:我发现,Hibernate不会缓存临时成员(请参阅),因此ehcache无论如何都不应将其视为临时成员。对吗

简短回答

事实证明,我遇到的问题是在我的模型中使用Joda时间实例(我用来映射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图


      最后我发现并解决了它

      我调查了这篇文章,发现我们的问题与Hibernate没有任何关系;事实上,ehcache 2.10.3和可能更早的版本都有一个预配置的过滤器,似乎是正确的(
      ehcache-2.10.3.jar!/net/sf/ehcache/pool/builtin sizeof.filter
      )。这篇文章很有趣,因为我找到了一种方法,通过在
      net.sf.ehcache.pool
      上启用调试日志并设置
      static{System.setProperty(“net.sf.ehcache.sizeof.verboseDebugLogging”,“true”);}
      来查找添加到缓存中的条目。原来是一个由Spring
      @Cacheable
      注释的服务返回了一个
      ResourceBundle
      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. [...]