【问题标题】:Second Level Cache never hits using, spring3, hibernate4, ehcache?二级缓存永远不会命中使用,spring3,hibernate4,ehcache?
【发布时间】:2014-09-09 12:51:13
【问题描述】:

使用版本;

    <spring.version>3.2.8.RELEASE</spring.version>
    <hibernate.version>4.2.11.Final</hibernate.version>

休眠配置;

...
<bean id="jpaAdapter"
      class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"
      p:database="${jpa.database}" p:showSql="${jpa.showSql}"/>


<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>

    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.hbm2ddl.auto">auto</prop>
            <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>
            <prop key="hibernate.connection.autocommit">true</prop>

            <prop key="hibernate.cache.use_second_level_cache">true</prop>
            <prop key="hibernate.cache.use_query_cache">true</prop>
            <prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</prop>

            <!--useful for debugging-->
            <prop key="hibernate.generate_statistics">true</prop>
        </props>
    </property>
    <property name="packagesToScan" value="info.hevi.learn.spring3hibernate4ehcache"/>
</bean>

<bean id="transactionManager"
      class="org.springframework.orm.hibernate4.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>
...

ehcache 配置(ehcache.xml);

<cache name="countryCache"
       maxElementsInMemory="300"
       eternal="true"
       overflowToDisk="false"
       timeToIdleSeconds="12000"
       timeToLiveSeconds="12000"
       diskPersistent="false"
       diskExpiryThreadIntervalSeconds="120"
       memoryStoreEvictionPolicy="LRU"  />

<cache name="info.hevi.learn.spring3hibernate4ehcache.domain.Country"
       maxElementsInMemory="300"
       eternal="true"
       overflowToDisk="false"
       timeToIdleSeconds="12000"
       timeToLiveSeconds="12000"
       diskPersistent="false"
       diskExpiryThreadIntervalSeconds="120"
       memoryStoreEvictionPolicy="LRU"  />

域类;

public class Language implements IEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Column(nullable = false, unique = true)
    private String name;
    ...
}

@Entity
@Table(name = "countries")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@NamedQueries({
        @NamedQuery(name="Country.findLanguagesByCountryId",query="select language from Country country inner join country.languages language where country.id=:cid")
})
public class Country implements IEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Column
    private String name;

    @Column
    private Integer population;

    @Column(updatable = false, insertable = false)
    @Temporal(TemporalType.TIMESTAMP)
    private Calendar creation;


    @ManyToMany(targetEntity = Language.class, fetch = FetchType.EAGER)
    @JoinTable(name = "country_language", joinColumns = {@JoinColumn(name = "cid")}, inverseJoinColumns = {@JoinColumn(name = "lid")})
    private Set<Language> languages;
    ...
}

和服务等级;

@Service(value = "countryService")
public class CountryService extends AbstractBasicService<Country, Long, ICountryDao> implements ICountryService {
...
    @Override
    @Cacheable(value = "countryCache")
    @Transactional
    public List<Country> getAll() {
        return super.getAll();
    }
...
}

和测试代码;

    @Test
public void testCache() {

    countryService.getAll();
    countryService.getAll();
    countryService.getAll();

}

最后是静态;

    07-18-2014 02:26:42,991 PM  INFO StatisticalLoggingSessionEventListener:275 - Session Metrics {
    57541 nanoseconds spent acquiring 1 JDBC connections;
    0 nanoseconds spent releasing 0 JDBC connections;
    834336 nanoseconds spent preparing 1 JDBC statements;
    1394341 nanoseconds spent executing 1 JDBC statements;
    0 nanoseconds spent executing 0 JDBC batches;
    317686 nanoseconds spent performing 7 L2C puts;
    0 nanoseconds spent performing 0 L2C hits;
    0 nanoseconds spent performing 0 L2C misses;
    655636 nanoseconds spent executing 1 flushes (flushing a total of 11 entities and 7 collections);
    109408 nanoseconds spent executing 1 partial-flushes (flushing a total of 0 entities and 0 collections)
}
07-18-2014 02:26:43,003 PM  INFO StatisticalLoggingSessionEventListener:275 - Session Metrics {
    31202 nanoseconds spent acquiring 1 JDBC connections;
    0 nanoseconds spent releasing 0 JDBC connections;
    351321 nanoseconds spent preparing 1 JDBC statements;
    1095294 nanoseconds spent executing 1 JDBC statements;
    0 nanoseconds spent executing 0 JDBC batches;
    281218 nanoseconds spent performing 7 L2C puts;
    0 nanoseconds spent performing 0 L2C hits;
    0 nanoseconds spent performing 0 L2C misses;
    579456 nanoseconds spent executing 1 flushes (flushing a total of 11 entities and 7 collections);
    11346 nanoseconds spent executing 1 partial-flushes (flushing a total of 0 entities and 0 collections)
}
07-18-2014 02:26:43,015 PM  INFO StatisticalLoggingSessionEventListener:275 - Session Metrics {
    23502 nanoseconds spent acquiring 1 JDBC connections;
    0 nanoseconds spent releasing 0 JDBC connections;
    366313 nanoseconds spent preparing 1 JDBC statements;
    695348 nanoseconds spent executing 1 JDBC statements;
    0 nanoseconds spent executing 0 JDBC batches;
    274329 nanoseconds spent performing 7 L2C puts;
    0 nanoseconds spent performing 0 L2C hits;
    0 nanoseconds spent performing 0 L2C misses;
    816100 nanoseconds spent executing 1 flushes (flushing a total of 11 entities and 7 collections);
    8509 nanoseconds spent executing 1 partial-flushes (flushing a total of 0 entities and 0 collections)
}

如您所见,它永远不会命中缓存,总是放置!我还调试了服务功能,它实际上执行了如果它真的缓存就不会发生的功能。怎么了?我错过了 javar arg 还是犯了语义错误?

【问题讨论】:

    标签: java spring hibernate jpa second-level-cache


    【解决方案1】:
    1. 尝试删除:

      <prop key="hibernate.connection.autocommit">true</prop>
      
    2. 从以下位置收集统计信息:

      SessionFactory.getStatistics().getSecondLevelCacheStatistics()
      
    3. 尝试使用

      通过它的 id 获取实体
      • session.get 或 session.load:
      • entityManager.find 或 entityManager.getReference

      实体加载进入二级缓存,然后二级缓存仅在没有加载此类实体时才访问数据库

    4. 对于像

      这样的方法
      countryService.getAll();
      

      这也意味着查询缓存,您需要为每个特定查询显式激活查询缓存:

      query.setCacheable(true);
      

    【讨论】:

    • query.setCacheable(true);为我工作。但是当我在 dao 级别使用查询时,有没有办法将逻辑移动到服务级别?以及如何驱逐查询缓存?
    • 你可以使用@NamedQuery(name = "queryName", query = "your query", hints = { @QueryHint(name = "org.hibernate.cacheable", value = "true") } ) 以简化缓存激活。关于缓存驱逐,Hibernate 会自动处理它。
    • 有趣的是,当我在工作中查看另一个项目(巨大且大量使用缓存)时​​,我发现在类似情况下没有执行任何操作的 getAll 函数在第二次运行时会命中缓存? ??我一定是错过了什么
    • 可能是使用spring cache来记忆服务方法结果,完全绕过了数据层。
    • 你似乎是对的,但这次 @Cacheable(value = "countryByNameCache", key = "#name") public Country getByName(String name) 没有得到任何点击
    猜你喜欢
    • 2011-06-27
    • 1970-01-01
    • 1970-01-01
    • 2012-12-12
    • 2014-06-21
    • 2014-11-10
    • 1970-01-01
    • 2013-11-23
    • 2015-04-24
    相关资源
    最近更新 更多