当前位置: 首页 > 知识库问答 >
问题:

二级缓存在Hibernate Spring JPA和EhCache中不工作

马阳晖
2023-03-14

让我澄清一下我对二级缓存的理解。在我的web应用程序的基类中有一个查询。几乎每一个操作都会调用此查询(我使用的是Struts,这就是应用程序的设计方式,因此不会真正弄乱它),例如,加载我的主页会调用三个单独的Struts操作,并为每个操作执行此查询。QueryDsl形式的查询看起来像Iterable

此查询占用自己的最长时间约10秒,因此它使应用程序非常慢,因为它对web应用程序的每个操作(CRUD)都进行了调用。根据我的理解,在启用二级缓存时,hibernate Spring orm应该从缓存中获取结果并避免数据库请求。然而,它不起作用。坚持。xml如下所示

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/jdbc
                       http://www.springframework.org/schema/jdbc/spring-jdbc-3.1.xsd
                       http://www.springframework.org/schema/beans
                       http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
                       http://www.springframework.org/schema/tx
                       http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">



<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" depends-on="flyway">
    <property name="dataSource" ref="dataSource" />
    <property name="packagesToScan" value="de.mm.moreevent.type" />
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
            <property name="showSql" value="false" />
            <property name="databasePlatform" value="org.hibernate.dialect.PostgreSQLDialect" />
            <property name="generateDdl" value="true" />
        </bean>
    </property>
<property name="jpaPropertyMap">
    <map>
        <entry key="hibernate.cache.use_query_cache" value="true" />
        <entry key="hibernate.cache.use_second_level_cache" value="true" />
        <entry key="hibernate.cache.region.factory_class" value="org.hibernate.cache.ehcache.EhCacheRegionFactory" />
        <entry key="hibernate.cache.default_cache_concurrency_strategy" value="read-write" />
        <entry key="javax.persistence.sharedCache.mode" value="ALL" />
        <entry key="hibernate.generate_statistics" value="false" />
    </map>
</property>
</bean>

<tx:annotation-driven transaction-manager="transactionManager"/>
<!-- see: http://springcert.sourceforge.net/2.5/4-study-transaction-management.html -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <tx:attributes>
        <tx:method name="makeBooking" read-only="false" propagation="NESTED" rollback-for="de.mm.moreevent.exception.ManagerException" />
        <tx:method name="sendConfirmationAndInvoice" read-only="true" propagation="NESTED" rollback-for="de.mm.moreevent.exception.ManagerException" />
        <tx:method name="sendConfirmationOnly" read-only="true" propagation="NESTED" rollback-for="de.mm.moreevent.exception.ManagerException" />
        <tx:method name="saveOrUpdate" read-only="false" propagation="NESTED" rollback-for="de.mm.moreevent.exception.ManagerException" />
        <tx:method name="participantsImport" read-only="false" propagation="NESTED" rollback-for="de.mm.moreevent.exception.ManagerException" />
    </tx:attributes>

</tx:advice>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory" />
    <qualifier value="transactionManager" />
</bean>

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> <!-- class="org.springframework.jdbc.datasource.DriverManagerDataSource" -->
    <property name="driverClass">
        <value>org.postgresql.Driver</value>
    </property>
    <property name="jdbcUrl">
        <value>jdbc:postgresql://127.0.0.1:port/dbName</value>
    </property>
    <property name="user">
        <value>user1</value>
    </property>
    <property name="password">
        <value>******</value>
    </property>
    <property name="initialPoolSize" value="5" />
    <property name="minPoolSize" value="5" />
    <property name="maxPoolSize" value="30" />
    <property name="idleConnectionTestPeriod" value="200" />
    <property name="acquireIncrement" value="1" />
    <property name="maxStatements" value="0" />
    <property name="numHelperThreads" value="3" />
</bean>

<!-- see: http://flywaydb.org/documentation/api.html  -->
<bean id="flyway" class="com.googlecode.flyway.core.Flyway" init-method="migrate">
    <property name="dataSource" ref="dataSource" />
     <property name="table" value="schema_version"></property>
     <property name="locations" value="customer/db-scripts/migration"/>
</bean>


<bean id="bouncyCastleProviderInitialisation" class="de.mm.moreevent.util.BouncyCastleProviderInitialisation" init-method="init" />

<bean id="strongEncryptorBC" class="org.jasypt.encryption.pbe.PooledPBEStringEncryptor">
    <property name="providerName">
        <value>BC</value>
    </property>
    <property name="algorithm">
        <value>algo</value>
    </property>
    <property name="password">
        <value>******</value>
    </property>
    <property name="poolSize">
        <value>4</value>
    </property>
</bean>

<bean id="hibernateStringEncryptor" class="org.jasypt.hibernate4.encryptor.HibernatePBEStringEncryptor">
    <property name="registeredName">
        <value>strongHibernateStringEncryptor</value>
    </property>
    <property name="encryptor">
        <ref bean="strongEncryptorBC" />
    </property>
</bean>

以下是Ehcache。xml

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
     name="cacheManager"
     updateCheck="false"
     maxBytesLocalHeap="100M"
     statistics="true">

<!--
 | Please see http://ehcache.sourceforge.net/documentation    /configuration.html for
 | detailed information on how to configurigure caches in this file
 +-->
<!-- Location of persistent caches on disk -->
<diskStore path="java.io.tmpdir/moreEventObjCache" />

<defaultCache eternal="false" maxElementsInMemory="100000"
    overflowToDisk="false" diskPersistent="false" timeToIdleSeconds="600"
    timeToLiveSeconds="600" memoryStoreEvictionPolicy="LRU" statistics="true"/>

<cache name="bookingTransaktions" eternal="true"
    overflowToDisk="false" diskPersistent="false"
    timeToIdleSeconds="0" timeToLiveSeconds="0" statistics="true"/>

<cache name="mailingBean" eternal="true" maxElementsInMemory="10000"
    overflowToDisk="false" diskPersistent="false"
    />

下面是我的实体类

import javax.persistence.Cacheable;
...    
@Entity 
@Table(name = "EVENT")
@Cacheable
@Configurable(dependencyCheck = true)
public class Event extends MoreEventDataBaseEntity implements CloneChangeEventI {
...

我正在测试执行查询所花费的时间,下面是代码(我连续两次调用同一查询)

    timer.mark();
    Iterable<Event> eventsFromDb = eventRepository.findAll(EventExpressions.queryAllEvents(), EventExpressions.orderByOnlineStartDate(true));
    timer.mark();
    Iterable<Event> eventsFromDb2 = eventRepository.findAll(EventExpressions.queryAllEvents(), EventExpressions.orderByOnlineStartDate(true));
    eventsFromDb2.getClass();
    timer.mark();

现在,在结果中,这个代码片段从网页中被调用三次,下面是控制台中的结果

init Struts page load: 
EventManager.java:130: +0ms

// Query fired first time, it took 8 seconds as expected  
EventManager.java:132: +8103ms
// Query fired second time, it took 15 ms due to so caching
EventManager.java:135: +15ms

init (Ajax1):
EventManager.java:130: +0ms
// Query fired and it took 9.5 sec, However I am expecting it to be few milliseconds ???? second level cache not working I suppose ????   
EventManager.java:132: +9501ms
EventManager.java:135: +21ms
Before timer 2016-09-09T14:21:41.853+02:00

init (Ajax2): 
EventManager.java:130: +1ms
???? took 9.5 seconds again. second level cache not working I suppose same as Ajax1????
EventManager.java:132: +9506ms
EventManager.java:135: +22ms

同样的事情发生在整个应用程序中。二级缓存根本不起作用。如果我可以通过缓存来节省这个查询执行时间,这将对我有很大的帮助。我正在使用Spring ORM 3.2.1,Hibernate EhCache 4.1.9


共有2个答案

白祺然
2023-03-14

我认为您应该使用不同的region factory类:

网旧金山。ehcache。冬眠EHCACHE区域工厂

http://www.ehcache.org/documentation/2.7/integrations/hibernate

另一方面,如果使用@Cacheable注解,则必须使用@Enable缓存或

<cache:annotation-driven />
宰父淳
2023-03-14

二级缓存不工作,因为您没有按ID获取数据(请参阅此链接何时以及如何使用hibernate二级缓存?)。

在您的情况下,您可以使用查询缓存。

 类似资料:
  • 在我的查询(查找)get cached会话关闭后,在一个新会话中,在我通过随机写入Sql查询更改数据库后,hibernate正在逐出所有内容,我如何才能阻止这种情况发生?我正在研究为那些很少改变的事情制定政策。 ecache。xml SpringHibernate配置

  • 当你使用本地(在内存中)缓存时,服务器可以缓存一些信息并快速地检索它,但是其他服务器不能访问这个缓存数据,他们需要到数据库中查询同样的信息。 如果你喜欢使用分布式缓存让其他服务器访问缓存的数据,由于它有一些序列化/反序列化和网络延迟开销,则需要注意:在某些情况下,它可能会降低性能。 缓存需要处理的另一个问题:缓存失效。 There are only two hard things in Compu

  • 我的应用程序使用Hibernate和EhCache作为二级缓存提供者。该应用程序部署在Wildfly 8.2上。二级缓存按预期配置并工作,但我不知道如何以通用方式在echache.xml配置中为二级缓存提供单独的配置。目前我的设置如下: 实体: pesistence.xml 还有ehcache.xml 虽然我将实体配置为使用ENTITY_ L2_ application.war#app_PU.EN

  • 我有一个spring/hibernate项目,我试图通过ehcache和terracotta将二级缓存添加到hibernate。一切似乎都很好,我甚至可以在terracota控制台中看到我试图缓存的实体的条目。但根据数据库的统计数据和日志,根本没有缓存任何内容! 负载命中率是0%,负载统计也是0。我做错了什么? 这是我所做的,我通过maven添加了所需的罐子。 更改了我的Hibernate属性以启

  • 1、一级缓存:指的是mybatis中sqlSession对象的缓存,当我们执行查询以后,查询的结果会同时存入sqlSession中,再次查询的时候,先去sqlSession中查询,有的话直接拿出,当sqlSession消失时,mybatis的一级缓存也就消失了,当调用sqlSession的修改、添加、删除、commit()、close()等方法时,会清空一级缓存。 2、二级缓存:指的是mybati

  • 本文向大家介绍Hibernate中一级缓存和二级缓存之间的区别,包括了Hibernate中一级缓存和二级缓存之间的区别的使用技巧和注意事项,需要的朋友参考一下 Hibernate支持两种类型的缓存,一种是第一级缓存,另一种是第二级缓存。  一级缓存是会话级缓存,它始终与会话级对象关联。这种类型的缓存用于通过缓存对象的状态来最小化Db交互。 那不是在事务中完成每次修改之后更新,而是仅在事务结束时更新