使用Infinispan和JBoss EAP 7.0.6的Hibernate L2C无效

时间:2017-08-23 12:37:29

标签: hibernate jboss infinispan

我有一个将Hibernate 5.0.9.Final部署到JBoss EAP 7.0.6的应用程序(默认情况下使用Infinispan 8.0.1.Final)。必须缓存几个实体,它们使用JPA的@Cacheable和Hibernate的@Cache进行注释,以提供每个实体的缓存策略。

代码库包含一个简单的测试,可以检查在本地运行的Infinispan以及可直接访问数据源的测试用例,也就是说,它们之间没有JBoss EAP,也没有Arquillian测试。测试成功运行,我可以看到实体在可用时从缓存中获取。

现在将应用程序部署到JBoss EAP并以负面体验运行结果。我可以在日志中看到Infinispan缓存实体。我还可以在JBoss Web控制台上看到缓存统计信息。当执行应该导致缓存命中计数的查询时,结果不会发生命中计数,而是查询命中数据源。

更新:使用persistence.xml中的相应属性启用了hibernate和infinispan统计信息。 L2C和查询缓存也是如此。区域工厂设置为JndiInfinispanRegionFactory,如http://infinispan.org/docs/8.0.x/user_guide/user_guide.html所述。此外,所有执行的查询都是JPQL查询。据我所知,告诉Infinispan和JBoss AS / 7使用他们的默认配置。

更新2: JBoss服务器实际上是EAP 7.0.6,而不是之前所说的AS / 7.

目前我们无法升级到更新版本的JBoss EAP(现在我恐怕没有Wildfly)。

顺便说一下,尝试在本地运行EhCache是​​成功的,但由于模块问题,在JBoss EAP中运行导致CNFE。

的persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            version="2.0" xmlns="http://java.sun.com/xml/ns/persistence"
            xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
   <persistence-unit name="DefaultUnit" transaction-type="JTA">
       <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
       <jta-data-source>java:/MyDataSource</jta-data-source>
       <class>...</class>
       <exclude-unlisted-classes>true</exclude-unlisted-classes>
       <shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
       <properties>
           <property name="hibernate.dialect" value="org.hibernate.dialect.DB2Dialect" />
           <property name="hibernate.show_sql" value="true" />
           <property name="hibernate.connection.datasource" value="java:/MyDataSource"/>
           <property name="hibernate.generate_statistics" value="true" />
           <property name="hibernate.cache.infinispan.statistics" value="true"/>
           <property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.JBossTransactionManagerLookup"/>
           <property name="hibernate.cache.use_second_level_cache" value="true" />
           <property name="hibernate.cache.use_query_cache" value="true" />
           <property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.infinispan.JndiInfinispanRegionFactory"/>
           <property name="hibernate.cache.infinispan.cachemanager" value="java:jboss/infinispan/container/hibernate"/>
       </properties>
   </persistence-unit>
</persistence>

standalone.xml 此块定义了hibernate容器

<cache-container name="hibernate" default-cache="local-query" module="org.hibernate.infinispan">
    <local-cache name="entity">
        <transaction mode="FULL_XA"/>
        <eviction strategy="LRU" max-entries="10000"/>
        <expiration max-idle="100000"/>
    </local-cache>
    <local-cache name="local-query">
        <eviction strategy="LRU" max-entries="10000"/>
        <expiration max-idle="100000"/>
    </local-cache>
    <local-cache name="timestamps"/>
</cache-container>

3 个答案:

答案 0 :(得分:1)

persistence.xml配置不正确。部署到EAP时,这就是所需要的:

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        version="2.0" xmlns="http://java.sun.com/xml/ns/persistence"
        xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
   <persistence-unit name="DefaultUnit" transaction-type="JTA">
       <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
       <jta-data-source>java:/MyDataSource</jta-data-source>
       <class>...</class>
       <exclude-unlisted-classes>true</exclude-unlisted-classes>
       <shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
       <properties>
           <property name="hibernate.dialect" value="org.hibernate.dialect.DB2Dialect" />
           <property name="hibernate.show_sql" value="true" />
           <property name="hibernate.connection.datasource" value="java:/MyDataSource"/>
           <property name="hibernate.generate_statistics" value="true" />
           <property name="hibernate.cache.infinispan.statistics" value="true"/>
           <property name="hibernate.cache.use_second_level_cache" value="true" />
           <property name="hibernate.cache.use_query_cache" value="true" />
       </properties>
   </persistence-unit>
</persistence>

通过定义您自己的区域工厂,您可能不会使用由EAP管理的实际Infinispan实例来检查您的统计信息。

查看EAP 7 documentation了解详情。

答案 1 :(得分:0)

  

当执行应该导致缓存命中计数的查询时   结果没有发生命中计数,查询命中数据源   代替。

当您说查询时,您的意思是JPQL查询还是Criteria API?

实体查询用于按实体标识符直接提取。对于查询,您也需要查询缓存,但不清楚这是否是您需要的。

此外,如果未启用统计信息,则命中计数可以为0:

  • 与Hibernate Core相关的hibernate.generate_statistics
  • 或者,hibernate.cache.infinispan.statistics,适用于Infinispan

找出问题的一种方法是调试DefaultLoadEventListener#doLoad方法:

entity = loadFromSecondLevelCache( event, persister, keyToLoad );

了解为什么无法从Infinispan获取它。

更新

  

此外,所有执行的查询都是JPQL查询。

您是否启用了查询缓存?

请注意,查询缓存使用单个区域,因此一旦添加/删除/修改属于该表空间的任何单个条目,所有使用某个表空间的查询结果都将被清除。

如果您在尝试加速JPQL时依赖实体二级缓存而不使用查询缓存,那么它的工作效率甚至会低于没有二级缓存的效率。那是因为JPQL无论如何都会执行SQL查询,因此您只需丢弃结果并转到Cache以通过其ID获取实体。如果在缓存中找不到实体,那实际上可能会变得非常糟糕,这意味着将发布大量的辅助查询。

正如我在我的书High-Performance Java Persistence中所解释的那样,如果您在执行读写事务时尝试卸载主节点,那么二级缓存会很有意义。对于只读查询,只需使用数据库复制并将负载分散到多个副本,这些副本的缓冲池配置为将整个工作集存储在RAM中。

答案 2 :(得分:-1)

我强烈建议避免这种组合:

  • JBoss AS7很古老,与Java 8不完全兼容
  • Infinispan 8需要Java 8

既然你声明你无法升级到WildFly(11即将到来!),那么你已经落后了近4个主要版本:这是很多缺失的错误修正和改进,但是你们的几代图书馆也有很大差异。重新组合。

我建议:

  • 坚持使用Ehcache
  • 坚持使用应用服务器中包含的旧版Hibernate ORM
  • 更新至WildFly 11: - )
  • 获得支持的JBoss EAP 7.x

我为EAP的商业参考道歉,但它可能是一个很好的解决方案,具体取决于您无法升级到WildFly的原因,因为它实际上是将更高版本(特别是兼容性固定为反向移植)与严格的API向后兼容性策略相结合。

关于Ehcache让你遇到模块问题,我很乐意为你提供帮助。模块系统很棒,我相信这可能很容易解决,但这可能更好地作为一个不同的问题/论坛来处理。