我们正在将我们的应用程序从JBoss EAP6.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内部代码为什么试图将实体缓存区域转换为查询结果缓存区域。
我尝试为每个缓存使用分隔的缓存,方法是使用Infinispan中定义的缓存hibernate.cache.infinispan.query.cfg本地查询来定义属性,但是Hibernate似乎没有考虑到它。
我在缓存方面非常初级,我必须承认,即使在阅读了大量文档之后,我也不完全理解自己在做什么。
版本:
下面是我们关心的pom.xml中的Maven依赖项声明(应用程序在几个Maven项目中被划分)
所有这些都在9.3.1版中。
这是存储在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>当试图装入2LC缓存时,WildFly独立实例没有正确启动,而是在初始化过程中崩溃,并给出以下堆栈跟踪。
将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)
...谢谢,
发布于 2019-07-12 09:35:33
最后,我找到了如何修复它。正如Radim所说,问题来自实体/集合缓存区域和查询缓存区域之间的冲突。
在与缓存相关的Hibernate文档中,我发现要定义查询或条件的缓存区域名称,必须使用setCacheRegion(String)方法。
通过在代码中搜索所有这些方法调用,我终于意识到在抽象泛型DAO类中,我们定义了如下查询区域名:
public HibernateGenericDao(Class<E> type) {
...
this.cacheRegion = type.getCanonicalName();
}然后在这里使用cacheRegion字段:
criteria.setCacheRegion(getCacheRegion());考虑到实体/集合缓存区域名也是由实体类完全限定的名称定义的(我们不知道如何定义),在查询缓存区域名后添加一个后缀,解决冲突并使应用程序正确启动。
this.cacheRegion = type.getCanonicalName().concat(QUERY_CACHE_REGION_PREFIX);谢谢,
发布于 2020-05-23 14:38:12
在迁移到WildFly 17.0.0.Final之后,我遇到了同样的问题。应用服务器已经在其模块文件夹中包含Hibernate 5.3.10。在调查了这个问题之后,我发现实际上Hibernate版本有https://hibernate.atlassian.net/browse/HHH-13586错误。由于我没有任何计划将我们的项目从WildFly 17迁移到更新版本,所以我决定修补Hibernate库的当前版本。因此,我刚刚下载了5.3.10版本,并通过https://github.com/hibernate/hibernate-orm/commit/2076c68ddff5dc39055e90e162a34c99c72261cb提交修补了hibernate-core模块,构建了它,并在WildFly模块文件夹中更改了原始hibernate-core库。java.lang.ClassCastException消失了。也许它会对别人有帮助。
https://stackoverflow.com/questions/56890059
复制相似问题