JPA学习(三)

本文详细介绍了JPA的二级缓存机制及其配置方法,包括如何启用和配置二级缓存,以提升数据访问效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、JPA二级缓存

首先看下面的案例(没有配置二级缓存):
@Test
	public  void testSecondCache(){
		Customer customer1 = entityManager.find(Customer.class, 3);
		Customer customer2 = entityManager.find(Customer.class, 3);
	}

使用上面的语句查询时会打印一条sql语句。
Hibernate: 
    select
        customer0_.id as id1_0_0_,
        customer0_.age as age2_0_0_,
        customer0_.birth as birth3_0_0_,
        customer0_.createDate as createDa4_0_0_,
        customer0_.email as email5_0_0_,
        customer0_.name as name6_0_0_ 
    from
        JPA_CUSTOMERS customer0_ 
    where
        customer0_.id=?
为什么会只打印一条sql呢?
原因是:JPA的一级缓存,属于Session级别的,在Session关闭的时候,一级缓存就失效了。

再看下面的实例:
@Test
	public  void testSecondCache(){
		Customer customer1 = entityManager.find(Customer.class, 3);
		transaction.commit();
		entityManager.close();//查询完成后提交事务,关闭entityManager
		
		//再次获取事务并开启
		entityManager=entityManagerFactory.createEntityManager();
		transaction = entityManager.getTransaction();
		transaction.begin();
		Customer customer2 = entityManager.find(Customer.class, 3);
	}
打印的sql如下:
Hibernate: 
    select
        customer0_.id as id1_0_0_,
        customer0_.age as age2_0_0_,
        customer0_.birth as birth3_0_0_,
        customer0_.createDate as createDa4_0_0_,
        customer0_.email as email5_0_0_,
        customer0_.name as name6_0_0_ 
    from
        JPA_CUSTOMERS customer0_ 
    where
        customer0_.id=?
Hibernate: 
    select
        customer0_.id as id1_0_0_,
        customer0_.age as age2_0_0_,
        customer0_.birth as birth3_0_0_,
        customer0_.createDate as createDa4_0_0_,
        customer0_.email as email5_0_0_,
        customer0_.name as name6_0_0_ 
    from
        JPA_CUSTOMERS customer0_ 
    where
        customer0_.id=?
这次打印了两条sql语句,原因是使用的不是同一个entityManager。

二、JPA二级缓存的配置

第一步:首先在实体类上添加@Cacheable(true)注解

/**
 * 
 */
package com.jpa.helloword;


import java.util.Date;

import javax.persistence.Cacheable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

import org.hibernate.annotations.Cache;

/**
 * @author 徐庶
 * @date 2016年12月10日
 */
@Cacheable(true)
@Table(name="JPA_CUSTOMERS")
@Entity
public class Customer {
	private  Integer id;
	private String name;
	private String email;
	private int age;
	private Date birth;
	private Date createDate;
	
	@Temporal(TemporalType.DATE)
	public Date getBirth() {
		return birth;
	}
	public void setBirth(Date birth) {
		this.birth = birth;
	}
	
	@Temporal(TemporalType.TIMESTAMP)
	public Date getCreateDate() {
		return createDate;
	}
	public void setCreateDate(Date createDate) {
		this.createDate = createDate;
	}
	@GeneratedValue(strategy=GenerationType.AUTO)
	@Id
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	@Override
	public String toString() {
		return "Customer [id=" + id + ", name=" + name + ", email=" + email
				+ ", age=" + age + ", birth=" + birth + ", createDate="
				+ createDate + "]";
	}
	
}
persistence.xml文件的配置:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
	<persistence-unit name="JPA_1" transaction-type="RESOURCE_LOCAL">
		<!-- 配置使用什么 ORM产品作为JPA的实现 -->
		<provider>org.hibernate.ejb.HibernatePersistence</provider>
		<!-- 添加持久化类 -->
		<class>com.jpa.helloword.Customer</class>
		<class>com.jpa.helloword.Order</class>
		<!-- 
		配置二级缓存的策略
		<shared-cache-mode> 节点:若 JPA 实现支持二级缓存,该节点可以配置在当前的持久化单元中是否启用二级缓存,可配置如下值:
		1.ALL:所有的实体类都被缓存
		2.NONE:所有的实体类都不被缓存. 
		3.ENABLE_SELECTIVE:标识 @Cacheable(true) 注解的实体类将被缓存
		4.DISABLE_SELECTIVE:缓存除标识 @Cacheable(false) 以外的所有实体类
		5.UNSPECIFIED:默认值,JPA 产品默认值将被使用
		 -->
		<shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
		<!-- 连接数据库配置 -->
		<properties>
			<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
			<property name="javax.persistence.jdbc.url" value="jdbc:mysql:///jpa"/>
			<property name="javax.persistence.jdbc.user" value="root"/>
			<property name="javax.persistence.jdbc.password" value="root"/>
		
		<!-- 配置JPA实现产品的配置  -->
		<property name="hibernate.format_sql" value="true"/>
		<property name="hibernate.show_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>
		<property name="hibernate.cache.use_query_cache" value="true"/>
		</properties>
	</persistence-unit>
</persistence>
添加ehcache.xml文件
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
    <!-- diskStore 配置磁盘存储
    	path: 保存的路径
     -->
    <diskStore path="d:/ehcache"/>
    <!-- defaultCache : 配置缓存细节
    	maxElementsInMemory :  二级缓存中,最大缓存对象的数量
    	eternal : 缓存的对象是否永久存储于内存中.
    	timeToIdleSeconds:(如果eternal配置为true.该配置无效.)对象在二级缓存中的最大空闲时间.
    	timeToLiveSeconds:(如果eternal配置为true.该配置无效.)对象在二级缓存中的最大存活时间.
    	overflowToDisk : 如果二级缓存中的对象超出了最大内存能容放的对象.是否溢出到硬盘上.
    	maxElementsOnDisk: 磁盘上最多能存放多少元素
    	diskPersistent : 在jvm关闭时,是否需要将内存中缓存的内容放入硬盘持久化.
    	diskExpiryThreadIntervalSeconds : 清理对象的轮询线程的轮询周期.
    	memoryStoreEvictionPolicy : 内存中对象超出了配置,移除策略是什么
    	 				Least Recently Used (specified as LRU). LRU(最近最少使用)
						First In First Out (specified as FIFO) 可选的有LFU(最不常使用)
						Less Frequently Used (specified as LFU) 和FIFO(先进先出) 
     -->
    <defaultCache
            maxElementsInMemory="10000"
            eternal="false"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            overflowToDisk="true"
            maxElementsOnDisk="10000000"
            diskPersistent="false"
            diskExpiryThreadIntervalSeconds="120"
            memoryStoreEvictionPolicy="LRU"
            />
</ehcache>

配置完成后测试:
//JPA二级缓存的测试
	@Test
	public  void testSecondCache(){
		Customer customer1 = entityManager.find(Customer.class, 3);
		transaction.commit();
		entityManager.close();//查询完成后提交事务,关闭entityManager
		
		//再次获取事务并开启
		entityManager=entityManagerFactory.createEntityManager();
		transaction = entityManager.getTransaction();
		transaction.begin();
		Customer customer2 = entityManager.find(Customer.class, 3);
	}
打印sql如下:
Hibernate: 
    select
        customer0_.id as id1_0_0_,
        customer0_.age as age2_0_0_,
        customer0_.birth as birth3_0_0_,
        customer0_.createDate as createDa4_0_0_,
        customer0_.email as email5_0_0_,
        customer0_.name as name6_0_0_ 
    from
        JPA_CUSTOMERS customer0_ 
    where
        customer0_.id=?
至此,JPA的二级缓存测试完成微笑





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值