当 Hibernate 查询缓存处于活动状态时,Wildfly 无法启动
Wildfly failed to start when Hibernate query cache is active
我们正在将我们的应用程序从 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内部代码试图将实体缓存区域转换为查询结果缓存区域。
我试图通过使用缓存 local-query 定义 属性 hibernate.cache.infinispan.query.cfg 来为每个缓存使用单独的缓存 在 Infinispan 配置中定义,但 Hibernate 似乎没有考虑它。
我是缓存的新手,我必须承认,即使阅读了很多文档,我也没有完全理解我在做什么。
版本:
- 休眠 5.3.6.Final
- Infinispan 9.3.1.Final
- 野蝇 14.0.1.Final
- OpenJDK 1.8
这里是我们关注的pom.xml中的Maven依赖声明(应用分为几个Maven项目)
- org.infinispan:infinispan-spring4-embedded (default/compile)
- 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.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)
...
谢谢,
我终于找到了解决方法。正如 Radim Vansa 所说,问题来自 entities/collection 缓存区域和查询缓存区域之间的冲突。
在与缓存相关的 Hibernate 文档中,我发现要为查询或条件定义缓存区域名称,必须使用 setCacheRegion(String)
方法。
通过在我们的代码中搜索所有这些方法调用,我终于意识到在我们的抽象通用 DAO class 中,我们定义查询区域名称如下:
public HibernateGenericDao(Class<E> type) {
...
this.cacheRegion = type.getCanonicalName();
}
然后在此处使用 cacheRegion 字段:
criteria.setCacheRegion(getCacheRegion());
鉴于 entities/collections 缓存区域名称也由实体 class fully-qualified 名称定义(我们不知道如何),附加一个后缀查询缓存区域名称解决冲突,使应用程序正常启动。
this.cacheRegion = type.getCanonicalName().concat(QUERY_CACHE_REGION_PREFIX);
谢谢,
我迁移到WildFly 17.0后遇到了同样的问题。0.Final。应用程序服务器的模块文件夹中已经包含 Hibernate 5.3.10。在调查问题后,我发现实际上 Hibernate 版本有 https://hibernate.atlassian.net/browse/HHH-13586 bug. As I didn't have any plans to migrate our project from WildFly 17 to a newer version I decided to patch the current version of the Hibernate library. So I just downloaded 5.3.10 version and patched hibernate-core module by the https://github.com/hibernate/hibernate-orm/commit/2076c68ddff5dc39055e90e162a34c99c72261cb 提交,构建它并更改 WildFly 模块文件夹中的原始 hibernate-core lib。 java.lang.ClassCastException 消失了。也许它会对其他人有所帮助。
我们正在将我们的应用程序从 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内部代码试图将实体缓存区域转换为查询结果缓存区域。
我试图通过使用缓存 local-query 定义 属性 hibernate.cache.infinispan.query.cfg 来为每个缓存使用单独的缓存 在 Infinispan 配置中定义,但 Hibernate 似乎没有考虑它。
我是缓存的新手,我必须承认,即使阅读了很多文档,我也没有完全理解我在做什么。
版本:
- 休眠 5.3.6.Final
- Infinispan 9.3.1.Final
- 野蝇 14.0.1.Final
- OpenJDK 1.8
这里是我们关注的pom.xml中的Maven依赖声明(应用分为几个Maven项目)
- org.infinispan:infinispan-spring4-embedded (default/compile)
- 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.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)
...
谢谢,
我终于找到了解决方法。正如 Radim Vansa 所说,问题来自 entities/collection 缓存区域和查询缓存区域之间的冲突。
在与缓存相关的 Hibernate 文档中,我发现要为查询或条件定义缓存区域名称,必须使用 setCacheRegion(String)
方法。
通过在我们的代码中搜索所有这些方法调用,我终于意识到在我们的抽象通用 DAO class 中,我们定义查询区域名称如下:
public HibernateGenericDao(Class<E> type) {
...
this.cacheRegion = type.getCanonicalName();
}
然后在此处使用 cacheRegion 字段:
criteria.setCacheRegion(getCacheRegion());
鉴于 entities/collections 缓存区域名称也由实体 class fully-qualified 名称定义(我们不知道如何),附加一个后缀查询缓存区域名称解决冲突,使应用程序正常启动。
this.cacheRegion = type.getCanonicalName().concat(QUERY_CACHE_REGION_PREFIX);
谢谢,
我迁移到WildFly 17.0后遇到了同样的问题。0.Final。应用程序服务器的模块文件夹中已经包含 Hibernate 5.3.10。在调查问题后,我发现实际上 Hibernate 版本有 https://hibernate.atlassian.net/browse/HHH-13586 bug. As I didn't have any plans to migrate our project from WildFly 17 to a newer version I decided to patch the current version of the Hibernate library. So I just downloaded 5.3.10 version and patched hibernate-core module by the https://github.com/hibernate/hibernate-orm/commit/2076c68ddff5dc39055e90e162a34c99c72261cb 提交,构建它并更改 WildFly 模块文件夹中的原始 hibernate-core lib。 java.lang.ClassCastException 消失了。也许它会对其他人有所帮助。