Java 当Hibernate查询缓存处于活动状态时,Wildfly无法启动
我们正在将应用程序从JBoss EAP 6.4迁移到WildFly 14。我们遇到了Hibernate和Infinispan的问题 该应用程序配置为使用Hibernate的二级缓存(也称为2LC)和Infinispan提供的Wildfly 在启用2LC缓存但禁用查询缓存的情况下,应用程序将启动并正常工作 但是,当我们尝试再次启用查询缓存(属性hibernate.cache.use\u query\u cache设置为true)时,它在初始化过程中崩溃,给出了连接的堆栈跟踪Java 当Hibernate查询缓存处于活动状态时,Wildfly无法启动,java,hibernate,wildfly,infinispan,second-level-cache,Java,Hibernate,Wildfly,Infinispan,Second Level Cache,我们正在将应用程序从JBoss EAP 6.4迁移到WildFly 14。我们遇到了Hibernate和Infinispan的问题 该应用程序配置为使用Hibernate的二级缓存(也称为2LC)和Infinispan提供的Wildfly 在启用2LC缓存但禁用查询缓存的情况下,应用程序将启动并正常工作 但是,当我们尝试再次启用查询缓存(属性hibernate.cache.use\u query\u cache设置为true)时,它在初始化过程中崩溃,给出了连接的堆栈跟踪 java.lang.C
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和infinispan配置中定义的缓存local query,但hibernate似乎没有考虑到这一点
我是缓存方面的新手,我必须承认,即使在阅读了大量文档之后,我也不完全理解我在做什么
版本:
- Hibernate 5.3.6.1最终版本
- 英菲尼斯潘9.3.1.1决赛
- WildFly 14.0.1.1决赛
- OpenJDK1.8
- org.infinispan:infinispan-spring4-embedded(默认/编译)
- org.infinispan:infinispan核心(已提供)
- 组织infinispan:infinispancommons(已提供)
- org.infinispan:infinispan-hibernate-cache-v53(已提供)
- org.infinispan:infinispan hibernate缓存spi(已提供)
- org.infinispan:infinispan hibernate缓存共享(已提供)
...
jboss部署结构.xml的依赖项部分
...
我们的Infinispan配置文件:
WildFly standalone实例没有正确启动,而是在尝试装载2LC缓存时在初始化过程中崩溃,并给出以下堆栈跟踪
设置hibernate.cache.use\u query\u cachetofalse修复了问题,但我们确实需要查询缓存
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)
...
谢谢,我终于找到了解决方法。正如Radim Vansa所说,问题来自实体/集合缓存区域和查询缓存区域之间的冲突 在与缓存相关的Hibernate文档中,我发现要为查询或条件定义缓存区域名称,必须使用
setCacheRegion(String)
方法
通过在代码中搜索所有这些方法调用,我最终意识到,在抽象泛型DAO类中,我们定义了如下查询区域名称:
公共HibernateGenericDao(类类型){
...
this.cacheRegion=type.getCanonicalName();
}
然后在此处使用cacheRegion字段:
criteria.setCacheRegion(getCacheRegion());
鉴于实体/集合缓存区域名称也是由实体类完全限定名称定义的(我们不知道如何定义),在查询缓存区域名称后添加后缀,以解决冲突并使应用程序正确启动
this.cacheRegion=type.getCanonicalName().concat(查询\缓存\区域\前缀);
谢谢,我终于找到了解决方法。正如Radim Vansa所说,问题来自实体/集合缓存区域和查询缓存区域之间的冲突 在与缓存相关的Hibernate文档中,我发现要为查询或条件定义缓存区域名称,必须使用
setCacheRegion(String)
方法
通过在代码中搜索所有这些方法调用,我最终意识到,在抽象泛型DAO类中,我们定义了如下查询区域名称:
公共HibernateGenericDao(类类型){
...
this.cacheRegion=type.getCanonicalName();
}
然后在此处使用cacheRegion字段:
criteria.setCacheRegion(getCacheRegion());
鉴于实体/集合缓存区域名称也是由实体类完全限定名称定义的(我们不知道如何定义),在查询缓存区域名称后添加后缀,以解决冲突并使应用程序正确启动
this.cacheRegion=type.getCanonicalName().concat(查询\缓存\区域\前缀);
谢谢,在迁移到WildFly 17.0.0.Final后,我遇到了同样的问题。应用服务器的模块文件夹中已经包含Hibernate 5.3.10。在调查了这个问题之后,我发现Hibernate版本实际上有这个bug。由于我没有任何计划将我们的项目从WildFly 17迁移到更新的版本,我决定修补Hibernate库的当前版本。因此,我刚刚下载了5.3.10版本,并通过提交对hibernate核心模块进行了修补,构建了它,并在WildFly模块文件夹中更改了原始的hibernate核心库。java.lang.ClassCastException消失了。也许它会帮助其他人。