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
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拦截,然后通过几个缓存存储记录好彼此关系,在修改的时候去更新。然而觉得代码量有点蛋碎,还是重复造轮子。