我有一个将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>
答案 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.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)
我强烈建议避免这种组合:
既然你声明你无法升级到WildFly(11即将到来!),那么你已经落后了近4个主要版本:这是很多缺失的错误修正和改进,但是你们的几代图书馆也有很大差异。重新组合。
我建议:
我为EAP的商业参考道歉,但它可能是一个很好的解决方案,具体取决于您无法升级到WildFly的原因,因为它实际上是将更高版本(特别是兼容性固定为反向移植)与严格的API向后兼容性策略相结合。
关于Ehcache让你遇到模块问题,我很乐意为你提供帮助。模块系统很棒,我相信这可能很容易解决,但这可能更好地作为一个不同的问题/论坛来处理。