JPA-二级缓存
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com</groupId> <artifactId>jpa</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.14</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>5.4.1.Final</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-jpamodelgen</artifactId> <version>5.4.1.Final</version> <scope>provided</scope> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <!-- 指定jdk --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build> </project>
persistence.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd" version="2.2"> <persistence-unit name="jpaname"> <!-- 实体类 --> <class>com.jpa.yingshe.Customer</class> <properties> <!-- 数据库信息 --> <property name="javax.persistence.jdbc.driver" value="com.mysql.cj.jdbc.Driver"/> <property name="javax.persistence.jdbc.url" value="jdbc:mysql://192.168.8.136/jpa?useSSL=false"/> <property name="javax.persistence.jdbc.user" value="root"/> <property name="javax.persistence.jdbc.password" value="root"/> <!-- 配置 hibernate 属性 --> <property name="hibernate.format_sql" value="true"/> <property name="hibernate.show_sql" value="true"/> <property name="hibernate.hbm2ddl.auto" value="update"/> </properties> </persistence-unit> </persistence>
Customer
package com.jpa.yingshe; import javax.persistence.*; @Table(name = "JPA_CUTOMERS") @Entity public class Customer { private Integer id; private String lastName; private String email; public Customer() { } public Customer(String lastName) { this.lastName = lastName; } @GeneratedValue(strategy = GenerationType.AUTO) @Id public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } @Column(name = "LAST_NAME", length = 50, nullable = false) public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } }
测试
先看JPA自带的一级缓存
package jpa.test; import com.jpa.yingshe.Customer; import org.junit.After; import org.junit.Before; import org.junit.Test; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.EntityTransaction; import javax.persistence.Persistence; public class JPAyingshe { private EntityManagerFactory entityManagerFactory; private EntityManager entityManager; private EntityTransaction transaction; @Before public void init() { entityManagerFactory = Persistence.createEntityManagerFactory("jpaname"); entityManager = entityManagerFactory.createEntityManager(); transaction = entityManager.getTransaction(); transaction.begin(); } @After public void destroy() { transaction.commit(); entityManager.close(); entityManagerFactory.close(); } @Test public void testFirstLevelCache() { Customer customer1 = entityManager.find(Customer.class, 1); Customer customer2 = entityManager.find(Customer.class, 1); } }
中间关闭会话再试试
@Test public void testFirstLevelCache() { Customer customer1 = entityManager.find(Customer.class, 1); transaction.commit(); entityManager.close(); entityManager = entityManagerFactory.createEntityManager(); transaction = entityManager.getTransaction(); transaction.begin(); Customer customer2 = entityManager.find(Customer.class, 1); }
配置二级缓存,让关闭会话后也只发送一次查询
添加 ehcache 依赖
<dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-ehcache</artifactId> <version>5.4.1.Final</version> </dependency> <dependency> <groupId>org.ehcache</groupId> <artifactId>ehcache</artifactId> <version>3.6.3</version> </dependency>
添加 ehcache.xml 配置
<ehcache> <diskStore path="./target/tmp"/> <defaultCache maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true" /> <cache name="sampleCache1" maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="300" timeToLiveSeconds="600" overflowToDisk="true" /> <cache name="sampleCache2" maxElementsInMemory="1000" eternal="true" timeToIdleSeconds="0" timeToLiveSeconds="0" overflowToDisk="false" /> --> </ehcache>
修改 persistence.xml 配置
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd" version="2.2"> <persistence-unit name="jpaname" transaction-type="RESOURCE_LOCAL"> <!-- 配置使用什么 ORM 产品来作为 JPA 的实现 --> <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider> <!-- 实体类 --> <class>com.jpa.yingshe.Customer</class> <!-- 配置二级缓存的策略 ALL:所有的实体类都被缓存 NONE:所有的实体类都不被缓存. ENABLE_SELECTIVE:标识 @Cacheable(true) 注解的实体类将被缓存 DISABLE_SELECTIVE:缓存除标识 @Cacheable(false) 以外的所有实体类 UNSPECIFIED:默认值,JPA 产品默认值将被使用 --> <shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode> <properties> <!-- 数据库信息 --> <property name="javax.persistence.jdbc.driver" value="com.mysql.cj.jdbc.Driver"/> <property name="javax.persistence.jdbc.url" value="jdbc:mysql://192.168.8.136/jpa?useSSL=false"/> <property name="javax.persistence.jdbc.user" value="root"/> <property name="javax.persistence.jdbc.password" value="root"/> <!-- 配置 hibernate 属性 --> <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.internal.EhcacheRegionFactory"/> <property name="hibernate.cache.use_query_cache" value="true"/> </properties> </persistence-unit> </persistence>
修改实体类,添加缓存注解
@Cacheable @Table(name = "JPA_CUTOMERS") @Entity public class Customer { private Integer id;
查询
@Test public void testSecondLevelCache() { Customer customer1 = entityManager.find(Customer.class, 1); transaction.commit(); entityManager.close(); entityManager = entityManagerFactory.createEntityManager(); transaction = entityManager.getTransaction(); transaction.begin(); Customer customer2 = entityManager.find(Customer.class, 1); }
项目结构