JPA 缓存

JPA  缓存

对于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">

<property name="showSql" value="true" />

<property name="generateDdl" value="true"/>

</bean>

</property>

<propertyname="jpaProperties">

<props>

<propkey="hibernate.cache.use_second_level_cache">true</prop>

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

<!--设置sharedCache.mode为ENABLE_SELECTIVE时,在实体上添加@Cacheable就可以被缓存-->

<prop key="javax.persistence.sharedCache.mode">ENABLE_SELECTIVE</prop>

<!--输出统计信息,在部署时需要关闭-->

<prop key="hibernate.generate_statistics">true</prop>

</props>

</property>

</bean>

注意:

u 实体上标注@cacheable时,需要设置javax.persistence.sharedCache.mode属性值;

u javax.persistence.sharedCache.mode

值可以为ENABLE_SELECTIVE(推荐值)、DISABLE_SELECTIVE、NONE、ALL;

若为ENABLE_SELECTIVE,则只要添加@Cacheable注解的实体才会被缓存;

若为DISABLE_SELECTIVE,则标注@Cacheable(value=false)的实体才被缓存;

若为NONE,任何实体都不会被缓存,即使被@Cacheable标注;

若为ALL,实体都会被缓存,即使没有@Cacheable标注;

u 开启Hibernate的查询缓存

除了设置

key="hibernate.cache.use_query_cache">true</prop>

外,还需要在JPA查询时采用@QueryHint来实现查询缓存,如下

public interface DictDao

{

// 通过@QueryHint来实现查询缓存。

@QueryHints({@QueryHint(name = "org.hibernate.cacheable", value ="true")})

List<Dict>findAll();

}

2、@Cache配置

采用org.hibernate.annotation.Cache配置时,设置如下:

<!--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">

<property name="showSql" value="true" />

<property name="generateDdl" value="true"/>

</bean>

</property>

<propertyname="jpaProperties">

<props>

<propkey="hibernate.cache.use_second_level_cache">true</prop>

<propkey="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</prop>

<!--输出统计信息,在部署时需要关闭-->

<prop key="hibernate.generate_statistics">true</prop>

</props>

</property>

</bean>

采用@cache时,除了在实体上标注@Cache外,还需要添加ehcache.xml配置文件,如下

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:noNamespaceSchemaLocation="ehcache.xsd">

<defaultCache

maxElementsInMemory="1000"

eternal="false"

timeToIdleSeconds="120"

timeToLiveSeconds="180"

overflowToDisk="false"

memoryStoreEvictionPolicy="LRU"

/>

<cache name="org.hibernate.cache.internal.StandardQueryCache"

maxElementsInMemory="100"

eternal="false"

timeToIdleSeconds="120"

timeToLiveSeconds="180"

overflowToDisk="true" />

<cache name="org.hibernate.cache.spi.UpdateTimestampsCache"

maxElementsInMemory="100"

eternal="false"

timeToIdleSeconds="120"

timeToLiveSeconds="180"

overflowToDisk="false" />

<!--单个实体的缓存设置,不设置采用默认设置-->

<!--

<cachename="org.ssl.template.model.Template"

maxElementsInMemory="100"

eternal="false"

timeToIdleSeconds="120"

timeToLiveSeconds="180"

overflowToDisk="false"

memoryStoreEvictionPolicy="LRU"

/>

-->

</ehcache>

注意:

u Hibernate3.x与Hibernate4.x开启二级缓存设置不同

Hibernate4.x:

<propkey="hibernate.cache.region.factory_class">

org.hibernate.cache.ehcache.EhCacheRegionFactory

</prop>

Hibernate3.x:

<prop key="hibernate.cache.provider_class ">

org.hibernate.cache.EhCacheProvider

</prop>

u 在部署项目时,需要将调试信息关闭,如关闭显示sql语句、关闭更新数据表、更改日志的输出级别等。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-05 23:56:14

JPA 缓存的相关文章

jpa缓存导致无法查询到更新后的数据&amp;android出现ANR的一个解决办法

1. 向服务器更新记录后查询,始终查询不到更新后的信息 只能查到更新之前的,马上推断出是缓存的问题.网上搜索一番,将问题定位为jpa缓存,我们要设置jpa查询时不从缓存中取,直接从数据库中取,这样便能保证查询到的结果是最新的,但是性能可能会有所影响.参考资料:https://en.wikibooks.org/wiki/Java_Persistence/Caching#JPA_2.0_Cache_APIs 如上图提示,我在restful服务器做了如下设置后便可以了. 2. 安卓app注册界面出新了

[Java Performance] 数据库性能最佳实践 - JPA缓存

JPA缓存(JPA Caching) JPA有两种类型的缓存: EntityManager自身就是一种缓存.事务中从数据库获取的和写入到数据库的数据会被缓存(什么样的数据会被缓存,在后面有介绍).在一个程序中也许会有很多个不同的EntityManager实例,每一个实例运行着不同的事务,拥有着它们自己的缓存. 当EntityManager提交一个事务后,它缓存的所有数据就会被合并到一个全局的缓存中.所有的EntityManager都能够访问这个全局的缓存. 全局缓存被称为二级缓存(Level 2

Spring Data Jpa缓存介绍

一级缓存: 会话session.事务级别的,事务退出,缓存就失效了.以id为标识 实体管理器-数据源 操作数据拷贝而非数据源. 二级缓存: 线程级或集群级,以id为标识放到缓存(针对id) 过程:一级缓存.二级缓存(进程级.可配置和修改)-数据源 多个线程访问二级缓存,需要采取事务控制 桥接第三方缓存,hibernate二级缓存的实现: 1.ehcache 2.OScache 3.JBossCache 4.Memcached ...... 什么样的数据适合二级缓存呢? 1.很少被修改的数据 2.

浅析JPA中EntityManager无法remove entity的问题

今天遇到一个奇怪的事情,利用EntityManager.remove(entity)方法删除一个entity时,删不掉,也不报错.后来经过多方查证,解决了这个问题. ERD Entity定义 ------------- 第一个Entity A --------------- @Entity public class A {     @Id     private Long id;          @Column(nullable = false, unique = true, length =

[Java Performance] 数据库性能最佳实践 - JPA和读写优化

数据库性能最佳实践 当应用需要连接数据库时,那么应用的性能就可能收到数据库性能的影响.比如当数据库的I/O能力存在限制,或者因缺失了索引而导致执行的SQL语句需要对整张表进行遍历.对于这些问题,仅仅对应用代码进行优化可能是不够,还需要了解数据库的知识和特点. 示例数据库 该数据库表示了128只股票在1年内(261个工作日)的股价信息. 其中有两张表:STOCKPRICE和STOCKOPTIONPRICE. STOCKPRICE中使用股票代码作为主键,另外还有日期字段.它有33408条记录(128

EntityManager无法remove entity的问题

今天遇到一个奇怪的事情,利用EntityManager.remove(entity)方法删除一个entity时,删不掉,也不报错.后来经过多方查证,解决了这个问题. ERD Entity定义 ------------- 第一个Entity A --------------- @Entity public class A {     @Id     private Long id;          @Column(nullable = false, unique = true, length =

JPA,EclipseLink 缓存机制学习(一) 树节点搜索问题引发的思考

最近在项目在使用JPA+EclipseLink 的方式进行开发,其中EclipseLink使用版本为2.5.1.遇到一些缓存方面使用不当造成的问题,从本篇开始逐步学习EclipseLink的缓存机制. 一.树节点搜索问题出现 故事是这样的:项目中有一个对树节点搜索的需求,如下图中所示,按照前缀匹配查询节点名称中包含OK的节点,将返回下图中的数据结构.基本实现就是:1.先查找出OK节点,然后根据该节点的父节点id获得父节点,也就是PERSON2结点,同样按照PERSON2的父结点id找到节点ROO

JPA学习笔记(11)——使用二级缓存

一级缓存 查询两次id为1的user User user1 = entityManager.find(User.class, 1); User user2 = entityManager.find(User.class, 1); 结果发现仅仅调用了一次sql查询,由于使用了一级缓存 假设查询一次后,关掉entityManager,再查询 User user1 = entityManager.find(User.class, 1); entityManager.close(); entityMan

JPA学习(五、JPA_二级缓存)

框架学习之JPA(五) JPA是Java Persistence API的简称,中文名Java持久层API,是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中. Sun引入新的JPA ORM规范出于两个原因:其一,简化现有Java EE和Java SE应用开发工作:其二,Sun希望整合ORM技术,实现天下归一. 学习视频:尚硅谷框架jpa学习(有兴趣的同学留言邮箱) 使用软件:eclipse Java版本:jdk8 本节目录 五.JPA_二级缓存 1.添