对于JPA2.0,缓存分为一级缓存和二级缓存(JPA1.0只支持一级缓存)。二级缓存通常是用来提高应用程序性能的,它可以避免访问以已经从数据库加载的数据,提高访问未被修改数据对象的速度。
持久化上下文就是JPA的一级缓存,通过在持久化上下文中存储持久化状态实体的快照,既可以进行脏检测,还可以当做持久化实体的缓存。一级缓存属于请求范围级别的缓存,如下
JPA二级缓存是跨越持久化上下文的,是真正意义上的全局应用缓存,如下
如果二级缓存激活,JPA会先从一级缓存中寻找实体,未找到再从二级缓存中寻找。当二级缓存有效时,就不能依靠事务来保护并发的数据,而是依靠锁策略,如在确认修改后,需要手工处理乐观锁失败等。
注意:二级缓存只能缓存通过EntityManager的find或getReference查询到的实体,以及通过实体的getter方法获取到的关联实体;而不能缓存通过JPQL查询获得的数据。
二级缓存通常用来提高性能,同时,使用二级缓存可能会导致提取到“陈旧”数据,也会出现并发写的问题。所以二级缓存最好是用在经常阅读数据,比较少更新数据的情况,而不应该对重要数据使用二级缓存。
对于不同的JPA实现产品,开启二级缓存的方式会有所不同,下面以 Spring+Hibernate为例,开启二级缓存,步骤如下
1) 添加hibernate-ehcache.jar文件,推荐使用maven来管理;
2) 修改Spring配置文件,开启二级缓存
3) 将需要缓存的实体类标注@ javax.persistence.Cacheable或org.hibernate.annotations.Cache。
1、@Cacheable配置
采用@javax.persistence.Cacheable配置,开启二级缓存如下
<!--jpa-->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="persistenceXmlLocation" value="classpath:META-INF/persistence.xml"/>
<property name="persistenceUnitName" value="template"/>
<property name="packagesToScan" value="org.ssl.template.model"/>
<!---指定JPA适配器-->
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"