JPA缓存

在JPA2.0以后,缓存分为一级缓存和二级缓存(JPA1.0只支持一级缓存)。

持久化上下文就是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包

<!-- hibernate-ehcache -->		
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-ehcache</artifactId>
			<version>5.2.17.Final</version>
		</dependency>

2)把ehcache的配置文件ehcache.xml加进来

<?xml version="1.0" encoding="UTF-8"?>
<ehcache>
	<diskStore path="d:/ehcache/"></diskStore>
	<!-- 默认缓存配置 -->
	<defaultCache 
		maxElementsInMemory="10000" 
		eternal="false"
		timeToIdleSeconds="120" 
		timeToLiveSeconds="120" 
		overflowToDisk="true" />
</ehcache>

3)在jpa的核心配置persistence.xml文件中,配置开启二级缓存

	<!-- name为项目工程名 -->
	<persistence-unit name="jpademo">
		<!--1、 jap是一个规范,是一个接口,它没有任何的具体实现,这里需要指定一个jpa具体实现 -->
		<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
		
		<shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
		<properties>
			<!-- 2、链接数据库的基本信息 -->
			<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
			<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/jpademo" />
			<property name="javax.persistence.jdbc.user" value="root" />
			<property name="javax.persistence.jdbc.password" value="123456" />
			<!--3、 jpa的具体实现,hibernate的基本属性 -->
			<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect" />
			<property name="hibernate.show_sql" value="true" />
			<property name="hibernate.format_sql" value="true" />
			<property name="hibernate.hbm2ddl.auto" value="update" />
			
			<!-- 开启二级缓存 -->
			<property name="hibernate.cache.use_second_level_cache" value="true"/>
			<!-- 配置二级缓存技术提供者 -->
			<property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.ehcache.EhCacheRegionFactory"/>
			<!-- 开启查询缓存 -->
			<property name="hibernate.cache.use_query_cache" value="true"  />
		</properties>

注意:

persistence.xml配置文件中 properties 标签前配置缓存策略:

<shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>

            

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配置文件中开启查询缓存:

<property name="hibernate.cache.use_query_cache" value="true" />

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<User> userlist = query.getResultList();
		System.out.println(userlist);

参考文章:https://blog.csdn.net/dac55300424/article/details/17145359?utm_source=blogxgwz0

猜你喜欢

转载自blog.csdn.net/qq_42402854/article/details/83212407
JPA