我在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
注释来限制图形的行走,但我不确定如何解决这个问题:
-
我是否必须忽略双向关联的一方以避免循环?
-
我是否必须明确忽略我的域模型类的瞬态成员?
-
一般来说,在将Hhnate与EhCache一起使用时使用
maxBytesLocalHeap
是否明智?或者我应该选择maxEntriesLocalHeap
,因为Hibernate为每个实体保留了一个单独的缓存区域?
[UPDATE] :我发现,临时成员不会被Hibernate缓存(参见Hibernate: Is it possible to save a transient field in second level cache?),所以不管怎样他们都不应该被ehcache看待 . 正确?
2 回答
Short answer
事实证明,我使用Jadira's UserType library来映射Joda类型的问题 .
Joda类型保留了各种内部引用(包括对时间顺序信息的引用,从而产生巨大的对象图),Ehcache的
SizeOfEngine
将这些引用引导到我的原始警告 .我发现如何配置SizeOfEngine引擎以排除这些引用没有干净的方法,但是我想再一个更简洁的方法是强制Hibernate只将相关信息放到第二级缓存中(我的时间实例)案例
LocalDateTimes
) .Update
Jadira在实现自定义类型时做出了糟糕的选择:参见my answer here
More Details
这是我发现的关于我的OP(使用Hibernate 4.2.15.Final,EhCache 2.6.9和UserType 3.2.0.GA):
首先,我对Hibernate如何在其中存储实体产生了误解's 2nd-Level cache. After reading Lorimer'博客文章关于Truly Understanding the Second-Level and Query Caches很多事情对我来说更有意义:
你没有't have to worry about bidirectional associations (or cyclic graphs for that matter), because Hibernate will only put IDs for your associations into the cache. And even if it would put a reference to the whole entity into the cache - which it doesn' t - EhCache的SizeOf引擎会跟踪已经访问过的图表中的对象,并且不会对它们进行两次调整 .
同样,您不必担心瞬态字段,因为Hibernate不会将它们放入缓存中
理论上,
maxBytesLocalHeap
配置应该没有任何问题 . 当您使用EhCache的SizeOf引擎未正确测量的自定义用户类型时,会出现问题 .我知道这是一个老问题 . 但它可能对某些人有用 . 我有同样的警告 . 我花了很多时间来解决这个问题 . 在我的例子中,EhCache不会忽略所有的hibernate代理类 . 我的实体有一些懒惰关联的字段,在测量大小期间,EhCache遍历整个休眠图 .
最后我找到this page并解决它 .