【发布时间】:2019-11-15 07:41:49
【问题描述】:
我们正在将我们的应用程序从 JBoss EAP 6.4 迁移到 WildFly 14。我们遇到了 Hibernate 和 Infinispan 的问题。
应用程序配置为使用 Hibernate 的二级缓存(也称为 2LC)和 Wildfly 提供的 Infinispan。
启用 2LC 缓存但禁用查询缓存后,应用程序启动并且似乎正常工作。
但是当我们尝试再次启用查询缓存(属性 hibernate.cache.use_query_cache 设置为 true)时,它会在初始化期间崩溃,并给出连接的堆栈跟踪。
java.lang.ClassCastException: org.infinispan.hibernate.cache.v53.impl.DomainDataRegionImpl cannot be cast to org.hibernate.cache.spi.QueryResultsRegion
在调试时,我不明白为什么管理二级缓存的Hibernate内部代码试图将实体缓存区域转换为查询结果缓存区域。
我尝试使用单独的缓存,通过定义属性 hibernate.cache.infinispan.query.cfg 与缓存 local-query 在Infinispan 配置,但是 Hibernate 似乎没有考虑到它。
我是缓存的初学者,我必须承认我并不完全理解我在做什么,即使在阅读了很多文档之后。
版本:
- 休眠 5.3.6.Final
- Infinispan 9.3.1.Final
- WildFly 14.0.1.Final
- OpenJDK 1.8
这里是我们关注的pom.xml中的Maven依赖声明(应用分为几个Maven项目)
- org.infinispan:infinispan-spring4-embedded(默认/编译)
- org.infinispan:infinispan-core(提供)
- org.infinispan:infinispan-commons(提供)
- org.infinispan:infinispan-hibernate-cache-v53(提供)
- org.infinispan:infinispan-hibernate-cache-spi(提供)
- org.infinispan:infinispan-hibernate-cache-commons(提供)
所有这些都在版本 9.3.1.Final
这是存储在 standalone.xml 中的缓存容器配置:
<subsystem xmlns="urn:jboss:domain:infinispan:7.0">
...
<cache-container name="hibernate" module="org.infinispan.hibernate-cache">
<local-cache name="entity">
<transaction mode="NON_XA"/>
<object-memory size="10000"/>
<expiration max-idle="100000"/>
</local-cache>
<local-cache name="local-query">
<object-memory size="10000"/>
<expiration max-idle="100000"/>
</local-cache>
<local-cache name="timestamps"/>
</cache-container>
</subsystem>
我们的 jboss-deployment-structure.xml 的依赖项部分。
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.2">
<deployment>
...
<dependencies>
<!-- Infinispan -->
<module name="org.infinispan" />
<module name="org.infinispan.commons" />
<module name="org.infinispan.hibernate-cache"/>
</dependencies>
</deployment>
</jboss-deployment-structure>
我们的 Infinispan 配置文件:
<infinispan
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:infinispan:config:7.0 http://www.infinispan.org/schemas/infinispan-config-7.0.xsd"
xmlns="urn:infinispan:config:7.0">
<threads />
<cache-container name="DefaultCacheManager"
statistics="true">
<transport />
<jmx duplicate-domains="true" />
<local-cache name="___defaultcache">
<transaction mode="NONE" />
</local-cache>
<local-cache name="defaultCache">
<transaction mode="NONE" />
<expiration lifespan="1000" max-idle="1000" interval="500" />
<memory>
<object size="1000" />
</memory>
<persistence passivation="false">
<file-store purge="false" read-only="false"
path="${jboss.server.temp.dir}/cacheservice" />
</persistence>
</local-cache>
<local-cache name="local-query">
<locking isolation="READ_COMMITTED" concurrency-level="1000"
acquire-timeout="15000" striping="false" />
<eviction max-entries="140000" strategy="LRU" />
<expiration max-idle="1200000" />
<transaction mode="NONE" auto-commit="false" />
</local-cache>
<!-- Other application caches ... -->
</cache-container>
</infinispan>
WildFly 独立实例在尝试装载 2LC 缓存时在初始化期间崩溃,而不是正确启动,并提供以下堆栈跟踪。
将 hibernate.cache.use_query_cache 设置为 false 可以解决问题,但我们确实需要查询缓存。
Caused by: java.lang.ClassCastException: org.infinispan.hibernate.cache.v53.impl.DomainDataRegionImpl cannot be cast to org.hibernate.cache.spi.QueryResultsRegion
at org.hibernate.cache.internal.EnabledCaching.makeQueryResultsRegionAccess(EnabledCaching.java:491)
at org.hibernate.cache.internal.EnabledCaching.getQueryResultsCache(EnabledCaching.java:478)
at org.hibernate.loader.Loader.listUsingQueryCache(Loader.java:2515)
at org.hibernate.loader.Loader.list(Loader.java:2498)
at org.hibernate.loader.criteria.CriteriaLoader.list(CriteriaLoader.java:109)
at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1959)
at org.hibernate.internal.CriteriaImpl.list(CriteriaImpl.java:370)
at fr.bdf.interop.middle.dao.hibernate.HibernateGenericDao.find(HibernateGenericDao.java:110)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:333)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:282)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
at com.sun.proxy.$Proxy204.find(Unknown Source)
...
谢谢,
【问题讨论】:
-
发生这种情况是因为您已经创建了应该保存与您请求保存查询数据的区域同名的实体/集合的区域。您是否为任何实体或任何查询设置区域名称?如果你正在调试这个,regionName 是什么?也发布你的 persistence.xml。
-
问题是我找不到代码定义哪个区域保存实体/集合或查询的位置。
-
持久化没有定义任何区域名称。调试时,我在 makeQueryResultsRegionAccess() 方法中看到与实体相关的区域名称。
标签: java hibernate wildfly infinispan second-level-cache