Hibernate提供了基于应用程序级别(进程)的缓存, 可以跨多个session,即不同的session都可以访问缓存数据。 这个换存也叫二级缓存。
Hibernate提供的二级缓存有默认的实现,且是一种可插配的缓存框架!如果用户想用二级缓存,只需要在hibernate.cfg.xml中配置即可; 不想用,直接移除,不影响代码。
hibernate.cfg.xml
<!--****************** 【二级缓存配置】****************** -->
<!-- a. 开启二级缓存 -->
<property name="hibernate.cache.use_second_level_cache">false</property> <!--未开启情况-->
<!-- b. 指定使用哪一个缓存框架(默认提供的实现) -->
<property name="hibernate.cache.provider_class">org.hibernate.cache.HashtableCacheProvider</property>
<!-- 开启查询缓存,放在class代码之前 -->
<property name="hibernate.cache.use_query_cache">true</property>
<!-- c. 指定哪一些类,需要加入二级缓存,一般在总配置中写,便于维护 -->
<class-cache usage="read-write" class="cn.itcast.b_second_cache.Dept"/>
<class-cache usage="read-only" class="cn.itcast.b_second_cache.Employee"/>
<!-- 集合缓存[集合缓存的元素对象,也加加入二级缓存] -->
<collection-cache usage="read-write" collection="cn.itcast.b_second_cache.Dept.emps"/>
Dept.java
package cn.itcast.b_second_cache;
import java.util.HashSet;
import java.util.Set;
public class Dept {
private int deptId;
private String deptName;
// 【一对多】 部门对应的多个员工
private Set<Employee> emps = new HashSet<Employee>();
public Dept(int deptId, String deptName) {
super();
this.deptId = deptId;
this.deptName = deptName;
}
public Dept() {
super();
}
public int getDeptId() {
return deptId;
}
public void setDeptId(int deptId) {
this.deptId = deptId;
}
public String getDeptName() {
return deptName;
}
public void setDeptName(String deptName) {
this.deptName = deptName;
}
public Set<Employee> getEmps() {
return emps;
}
public void setEmps(Set<Employee> emps) {
this.emps = emps;
}
@Override
public String toString() {
return "Dept [deptId=" + deptId + ", deptName=" + deptName + "]";
}
}
Employee.java
package cn.itcast.b_second_cache;
public class Employee {
private int empId;
private String empName;
private double salary;
// 【多对一】员工与部门
private Dept dept;;
public int getEmpId() {
return empId;
}
public void setEmpId(int empId) {
this.empId = empId;
}
public String getEmpName() {
return empName;
}
public void setEmpName(String empName) {
this.empName = empName;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public Dept getDept() {
return dept;
}
public void setDept(Dept dept) {
this.dept = dept;
}
}
Dept.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="cn.itcast.b_second_cache">
<class name="Dept" table="t_dept" >
<id name="deptId">
<generator class="native"></generator>
</id>
<property name="deptName" length="20"></property>
<set name="emps">
<key column="dept_id"></key>
<one-to-many class="Employee"/>
</set>
</class>
<!-- 存放sql语句 -->
<query name="getAllDept">
<![CDATA[
from Dept d where deptId < ?
]]>
</query>
</hibernate-mapping>
Employee.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="cn.itcast.b_second_cache">
<class name="Employee" table="t_employee">
<id name="empId">
<generator class="native"></generator>
</id>
<property name="empName" length="20"></property>
<property name="salary" type="double"></property>
<many-to-one name="dept" column="dept_id" class="Dept"></many-to-one>
</class>
</hibernate-mapping>
App.java
public class App {
private static SessionFactory sf;
static {
sf = new Configuration()
.configure()
.addClass(Dept.class)
.addClass(Employee.class) // 测试时候使用
.buildSessionFactory();
}
// 1. 测试二级缓存的使用
// 没有/有用 二级缓存
@Test
public void testCache() {
Session session1 = sf.openSession();
session1.beginTransaction();
// a. 查询一次
Dept dept = (Dept) session1.get(Dept.class, 3);
dept.getEmps().size();// 集合
session1.getTransaction().commit();
session1.close();
System.out.println("------");
// 第二个session
Session session2 = sf.openSession();
session2.beginTransaction();
// a. 查询一次
dept = (Dept) session2.get(Dept.class, 3); // 二级缓存配置好; 这里不查询数据库
//dept.setDeptName("市场行政部");
dept.getEmps().size();
session2.getTransaction().commit();
session2.close();
}
}
二级缓存未配置sql查询情况:
Hibernate: select dept0_.deptId as deptId0_0_, dept0_.deptName as deptName0_0_ from t_dept dept0_ where dept0_.deptId=?
Hibernate: select emps0_.dept_id as dept4_0_1_, emps0_.empId as empId1_, emps0_.empId as empId1_0_, emps0_.empName as empName1_0_, emps0_.salary as salary1_0_, emps0_.dept_id as dept4_1_0_ from t_employee emps0_ where emps0_.dept_id=?
------
Hibernate: select dept0_.deptId as deptId0_0_, dept0_.deptName as deptName0_0_ from t_dept dept0_ where dept0_.deptId=?
Hibernate: select emps0_.dept_id as dept4_0_1_, emps0_.empId as empId1_, emps0_.empId as empId1_0_, emps0_.empName as empName1_0_, emps0_.salary as salary1_0_, emps0_.dept_id as dept4_1_0_ from t_employee emps0_ where emps0_.dept_id=?
<!--****************** 【二级缓存配置】****************** -->
<!-- a. 开启二级缓存 -->
<property name="hibernate.cache.use_second_level_cache">true</property>
二级缓存配置sql查询情况:
Hibernate: select dept0_.deptId as deptId0_0_, dept0_.deptName as deptName0_0_ from t_dept dept0_ where dept0_.deptId=?
Hibernate: select emps0_.dept_id as dept4_0_1_, emps0_.empId as empId1_, emps0_.empId as empId1_0_, emps0_.empName as empName1_0_, emps0_.salary as salary1_0_, emps0_.dept_id as dept4_1_0_ from t_employee emps0_ where emps0_.dept_id=?
------