spring boot+spring data jpa +ehcache 缓存配置

pom.xml配置

        
            org.springframework.boot
            spring-boot-starter-cache
        
        
            org.hibernate
            hibernate-ehcache
        

boot启动文件

@EnableCaching//开启缓存
@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true)
@SpringBootApplication
public class ShoppingApplication extends SpringBootServletInitializer {

实体类

@javax.persistence.Cacheable
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE,region = BaseQueryService.CACHE)
public  class SystemRole extends BaseBean {

配置文件

spring.jpa.show-sql=true
spring.jpa.open-in-view=true
#统计
spring.jpa.properties.hibernate.generate_statistics=true
spring.jpa.properties.hibernate.javax.cache.missing_cache_strategy=create
spring.jpa.properties.hibernate.cache.format_sql=true
#开启查询缓存
spring.jpa.properties.hibernate.cache.use_query_cache=true
#缓存region 名称的前缀
spring.jpa.properties.hibernate.cache.region_prefix=lesson_cloud_
spring.jpa.properties.hibernate.cache.use_structured_entries=true
#要放在根目录下,不然就读取不到,这里指定的是@org.hibernate.annotations.Cache中的region 和setHint(QueryHints.HINT_CACHE_REGION, "")中的
spring.jpa.properties.hibernate.cache.provider_configuration_file_resource_path=ehcache.xml
#ENABLE_SELECTIVE除非明确标记为可缓存(使用@Cacheable注释),否则不会缓存实体。
spring.jpa.properties.javax.persistence.sharedCache.mode=ENABLE_SELECTIVE
#开启二级缓存
spring.jpa.properties.hibernate.cache.use_second_level_cache=true
#指定缓存provider
spring.jpa.properties.hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.EhCacheRegionFactory


#这里指定的是使用org.springframework.cache.annotation等注解缓存配置
spring.cache.ehcache.config=classpath:config/ehcache.xml
spring.cache.type=ehcache

然后在是用的时候要注意

我使用的是Spring Data JPA中的JpaSpecificationExecutor进行构建查询

public interface BaseJpa extends JpaRepository, JpaSpecificationExecutor {
}

发现问题缓存无效

JpaSpecificationExecutor下的方法

 Optional findOne(@Nullable Specification spec);

List findAll(@Nullable Specification spec, Sort sort);
Page findAll(@Nullable Specification spec, Pageable pageable);

 

这几个方法缓存都是无效的,但是其内部用@OneToOne等关联类的缓存是有效的

如findOne 查询到A,A中包含b

第一次进来,查询ab都被查,第二次,只查询了a,说明b缓存了。

而对于列表缓存,要通过@QueryHints去配置,太不智能了。

不知道有没有spring data jpa 通过代码设置缓存的

要使其查询条件和按照id查询能有效的进行缓存,我测试是通过entityManager才会生效

 List list=  entityManager.createQuery("SELECT u "+
                "FROM\n" +
                " SystemUser u",SystemUser.class)
                .setHint(QueryHints.HINT_CACHE_REGION, "entityCache")
                .setHint(QueryHints.HINT_CACHEABLE, "true").getResultList();

参考资料

https://www.cnblogs.com/qianzf/p/7476847.html

http://www.spring4all.com/article/1443

http://docs.jboss.org/hibernate/orm/5.0/userguide/html_single/Hibernate_User_Guide.html#caching-config

https://juejin.im/post/5b2b5fc8f265da595d2ebf43

注解说明

org.springframework.cache.annotation.CacheEvict;
org.springframework.cache.annotation.Cacheable;
org.springframework.cache.annotation.Caching;

是针对spring.cache的缓存,内部也是可以指定ehcache的

而针对jpa,因为底层的实现是Hibernate,所以使用的是

javax.persistence.Cacheable
org.hibernate.annotations.Cache

然后再说说一级和二级

在spring data jpa中,同一个session是具有缓存的,如在一次请求流程中使用的都是同一个entityManager

而二级缓存是不同session中能共享缓存,这包含多次请求共享缓存

 

最主要的是天真的我认为直接使用

org.springframework.cache.annotation.CacheEvict;
org.springframework.cache.annotation.Cacheable;
org.springframework.cache.annotation.Caching;

这几个缓存可以缓存数据库查询结果,减少查询。然后发现在处理实体有OneToOne等关系的实体类的时候,增删改关联的实体类,缓存的没有办法去提示更新

想想解决方案是通过aop拦截,然后通过几个缓存存储记录好彼此关系,在修改的时候去更新。然而觉得代码量有点蛋碎,还是重复造轮子。

 

 

你可能感兴趣的:(spring)