持久化上下文就是JPA的一级缓存,通过在持久化上下文中存储持久化状态实体的快照,既可以进行脏检测,还可以当做持久化实体的缓存。一级缓存属于请求范围级别的缓存。
二级缓存是跨越持久化上下文的,是真正意义上的全局应用缓存,二级缓存通常是用来提高应用程序性能的,它可以避免访问以已经从数据库加载的数据,提高访问未被修改数据对象的速度。
如果二级缓存激活,JPA会先从一级缓存中寻找实体,未找到再从二级缓存中寻找。当二级缓存有效时,就不能依靠事务来保护并发的数据,而是依靠锁策略,如在确认修改后,需要手工处理乐观锁失败等。
注意:二级缓存只能缓存通过EntityManager的find或getReference查询到的实体,以及通过实体的getter方法获取到的关联实体;而通过JPQL查询获得的数据缓存需要配置。
二级缓存通常用来提高性能,同时,使用二级缓存可能会导致提取到“陈旧”数据,也会出现并发写的问题。所以二级缓存最好是用在经常阅读数据,比较少更新数据的情况,而不应该对重要数据使用二级缓存。
对于不同的JPA实现产品,开启二级缓存的方式会有所不同,这里用我们用的是jpa2.1的hibernate5实现,
首先来看一级缓存:只有一条sql语句,说明一级缓存在起作用
User user = entityManager.find(User.class, 5);
User user2 = entityManager.find(User.class, 5);
System.out.println(user);
System.out.println(user2);
二级缓存:和Hibernate一样,一级缓存是默认就开启的,不用我们管理,二级缓存默认是关闭的
User user = entityManager.find(User.class, 5);
transaction.commit();
entityManager.close();
entityManager = entityManagerFactory.createEntityManager();
transaction = entityManager.getTransaction();
transaction.begin();
User user2 = entityManager.find(User.class, 5);
两次查询中间,提交了事务,关闭了EntityManger,一级缓存失效,发出两条sql语句,
开启二级缓存配置步骤:想要减少访问数据库的次数,就要开启二级缓存,像Hibernate一样选择使用ehcache作为二级缓存,
1)配置pom.xml,导入jar包
org.hibernate
hibernate-ehcache
5.2.17.Final
2)把ehcache的配置文件ehcache.xml加进来
3)在jpa的核心配置persistence.xml文件中,配置开启二级缓存
org.hibernate.jpa.HibernatePersistenceProvider
ENABLE_SELECTIVE
注意:
persistence.xml配置文件中 properties 标签前配置缓存策略:
ENABLE_SELECTIVE
shared-cached-mode这个标签有5个值:
a) ALL:缓存所有实体类
b) NONE:所有实体类都不缓存
c) ENABLE-SELECTED: 有@Cacheable(true) 的实体类被缓存(常用)
d) DISABLE-SELECTED: 除了有@cacheable(false)这个注解外的所有实体类
e) UNSPECIFIED:默认值,jpa的实现的默认值
然后二级缓存就开启了,再运行上面实例: 两次查询中间,提交了事务,关闭了EntityManger,只会发起一条sql
jpa使用jpql查询缓存:
persistence.xml配置文件中开启查询缓存:
query中开启查询缓存:query.setHint(QueryHints.HINT_CACHEABLE, true);
String jpql = "select u from User u";
Query query = entityManager.createQuery(jpql);
query.setHint(QueryHints.HINT_CACHEABLE, true);
List userlist = query.getResultList();
System.out.println(userlist);
参考文章:https://blog.csdn.net/dac55300424/article/details/17145359?utm_source=blogxgwz0