(20)Hibernate二级缓存

1、二级缓存的知识

创新互联主营津南网站建设的网络公司,主营网站建设方案,app开发定制,津南h5重庆小程序开发搭建,津南网站营销推广欢迎津南等地区企业咨询

Hibernate提供的缓存:有一级缓存二级缓存。 目的是为了减少对数据库的访问次数,提升程序执行效率!

一级缓存:基于Session的缓存,缓存内容只在当前session有效,session关闭,缓存内容失效!

特点:作用范围较小! 缓存的时间短。缓存效果不明显。

二级缓存

Hibernate提供了基于应用程序级别的缓存, 可以跨多个session,即不同的session都可以访问缓存数据。 这个缓存也叫二级缓存。

Hibernate提供的二级缓存有默认的实现,且是一种可插配的缓存框架!如果用户想用二级缓存,只需要在hibernate.cfg.xml中配置即可;不想用,直接移除,不影响代码。

如果用户觉得hibernate提供的框架不好用,可以换其他的缓存框架或自己实现缓存框架都可以。

下面的配置位于%hibernate%/project/etc/hibernate.properties中

##########################
### Second-level Cache ###
##########################

## disable the second-level cache 二级缓存默认不开启,需要手动开启
#hibernate.cache.use_second_level_cache false

## enable the query cache
#hibernate.cache.use_query_cache true 开启查询缓存

## choose a cache implementation 二级缓存框架的实现
#hibernate.cache.provider_class org.hibernate.cache.EhCacheProvider
#hibernate.cache.provider_class org.hibernate.cache.EmptyCacheProvider
hibernate.cache.provider_class org.hibernate.cache.HashtableCacheProvider
#hibernate.cache.provider_class org.hibernate.cache.TreeCacheProvider
#hibernate.cache.provider_class org.hibernate.cache.OSCacheProvider
#hibernate.cache.provider_class org.hibernate.cache.SwarmCacheProvider

缓存的并发策略

     放入二级缓存的对象,只读; 
  非严格的读写
    读写; 放入二级缓存的对象可以读、写;
   (基于事务的策略)

2、使用二级缓存

二级缓存,使用步骤

    1)开启二级缓存

true

    2)指定缓存框架

org.hibernate.cache.HashtableCacheProvider

    3)指定那些类加入二级缓存





    4)测试二级缓存!

示例代码和配置

hibernate.cfg.xml




    
    
        
        com.MySQL.jdbc.Driver
        jdbc:mysql:///test	
        root
        root
		
        org.hibernate.dialect.MySQL5Dialect
        
        
		
		true
		
		false
		
		update
		

		
		
		true
		
		org.hibernate.cache.HashtableCacheProvider
		
		true
		
		
		
		
		
		
    

Department.java

package com.rk.hibernate.cache;

import java.util.Set;

public class Department
{
	private int deptId;
	private String deptName;
	private Set emps;
	private int version;
	
	public int getVersion()
	{
		return version;
	}
	public void setVersion(int version)
	{
		this.version = version;
	}
	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 getEmps()
	{
		return emps;
	}
	public void setEmps(Set emps)
	{
		this.emps = emps;
	}
	@Override
	public String toString()
	{
		return "Department [deptId=" + deptId + ", deptName=" + deptName + "]";
	}
	
}

Department.hbm.xml




	
		
		
			
		
		
		
		
			
			
			
		
	


	

Employee.java

package com.rk.hibernate.cache;

public class Employee
{
	private int empId;
	private String empName;
	private int salary;
	private Department dept;
	private int version;
	
	public int getVersion()
	{
		return version;
	}
	public void setVersion(int version)
	{
		this.version = version;
	}
	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 int getSalary()
	{
		return salary;
	}
	public void setSalary(int salary)
	{
		this.salary = salary;
	}
	public Department getDept()
	{
		return dept;
	}
	public void setDept(Department dept)
	{
		this.dept = dept;
	}
	@Override
	public String toString()
	{
		return "Employee [empId=" + empId + ", empName=" + empName + ", salary=" + salary + "]";
	}
	
}

Employee.hbm.xml




	
		
		
			
		
		
		
		
		
	

App.java

package com.rk.hibernate.cache;

import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.junit.Test;


public class App
{
	private static SessionFactory sf;
	static
	{
		sf = new Configuration()
						.configure()
						.addClass(Department.class)
						.addClass(Employee.class)
						.buildSessionFactory();
	}
	
	
	// 1. 测试二级缓存的使用
	//思路:sesion本身提供了一级缓存,它是mandatory,不能关闭
	//二级缓存,是optional,通过配置文件可以开启,可以关闭。
	//如果不开启二级缓存,两个session查询同一个id的数据,会发送两个SQL语句
	//如果开启二级缓存,两个session查询同一个id的数据,会发送一条SQL语句
	//通过开启和关闭二级缓存,来查看执行的SQL数目
	@Test
	public void testSecondLevelCache()
	{
		//第1次查询,第一个session
		Session session1 = sf.openSession();
		session1.beginTransaction();		
		Department dept1 = (Department) session1.get(Department.class, 3);
		Set emps1 = dept1.getEmps();
		System.out.println(dept1);
		System.out.println(emps1);
		session1.getTransaction().commit();
		session1.close();
		
		System.out.println("-------------------------------");
		
		//第2次查询,第二个session
		Session session2 = sf.openSession();
		session2.beginTransaction();		
		Department dept2 = (Department) session2.get(Department.class, 3);
		Set emps2 = dept2.getEmps();
		System.out.println(dept2);		
		System.out.println(emps2);
		session2.getTransaction().commit();
		session2.close();
	}
	
	
	@Test
	public void testQueryCache()
	{
		// 第1次查询,第一个session
		Session session1 = sf.openSession();
		session1.beginTransaction();
		// HQL查询  【setCacheable  指定从二级缓存找,或者是放入二级缓存】
		Query q1 = session1.createQuery("from Department").setCacheable(true);
		List list1 = q1.list();
		System.out.println(list1);
		session1.getTransaction().commit();
		session1.close();

		System.out.println("-------------------------------");

		// 第2次查询,第二个session
		Session session2 = sf.openSession();
		session2.beginTransaction();
		// HQL查询  【setCacheable  指定从二级缓存找,或者是放入二级缓存】
		Query q2 = session2.createQuery("from Department").setCacheable(true);
		List list2 = q2.list();
		System.out.println(list2);
		session2.getTransaction().commit();
		session2.close();
	}
	
}

当我们开启二级缓存后,例如在上面的testSecondLevelCache()方法中,第一次从Session读取数据后,会存储在二级缓存上;第二次打开Session,程序再进行相同查询,就不需要再发送SQL语句,因为它会从二级缓存中读取数据。

有一点需要注意如果二级缓存中没有数据,第一次开启Session读取数据,并调用session.clear()方法,再读取数据,会发送两次SQL语句

	@Test
	public void test1()
	{
		// 第1次查询,第一个session
		Session session1 = sf.openSession();
		session1.beginTransaction();
		Department dept1 = (Department) session1.get(Department.class, 2);
		System.out.println(dept1);	
		System.out.println(dept1.getEmps());
		
		session1.clear();
		dept1 = (Department) session1.get(Department.class, 2);
		System.out.println(dept1);	
		System.out.println(dept1.getEmps());
		
		session1.getTransaction().commit();
		session1.close();

	}

结果如下:

Hibernate: select department0_.id as id0_0_, department0_.dept_version as dept2_0_0_, department0_.name as name0_0_ from T_Department department0_ where department0_.id=?
Department [deptId=2, deptName=woqu]
Hibernate: select emps0_.deptId as deptId0_1_, emps0_.id as id1_, emps0_.id as id1_0_, emps0_.emp_version as emp2_1_0_, emps0_.name as name1_0_, emps0_.salary as salary1_0_, emps0_.deptId as deptId1_0_ from T_Employee emps0_ where emps0_.deptId=?
[Employee [empId=3, empName=TO_T_, salary=4]]
Hibernate: select department0_.id as id0_0_, department0_.dept_version as dept2_0_0_, department0_.name as name0_0_ from T_Department department0_ where department0_.id=?
Department [deptId=2, deptName=woqu]
Hibernate: select emps0_.deptId as deptId0_1_, emps0_.id as id1_, emps0_.id as id1_0_, emps0_.emp_version as emp2_1_0_, emps0_.name as name1_0_, emps0_.salary as salary1_0_, emps0_.deptId as deptId1_0_ from T_Employee emps0_ where emps0_.deptId=?
[Employee [empId=3, empName=TO_T_, salary=4]]

如果二级缓存中已经存在数据,第二次开启Session,调用session.clear(),再读取数据,并不会发送SQL语句。

	@Test
	public void test1()
	{
		Session session2 = sf.openSession();
		session2.beginTransaction();
		Department dept2 = (Department) session2.get(Department.class, 2);
		System.out.println(dept2);	
		System.out.println(dept2.getEmps());
		
		session2.getTransaction().commit();
		session2.close();
		
		System.out.println("-------------------------------");
		
		
		// 第1次查询,第一个session
		Session session1 = sf.openSession();
		session1.beginTransaction();
		Department dept1 = (Department) session1.get(Department.class, 2);
		System.out.println(dept1);	
		System.out.println(dept1.getEmps());
		
		session1.clear();
		dept1 = (Department) session1.get(Department.class, 2);
		System.out.println(dept1);	
		System.out.println(dept1.getEmps());
		
		session1.getTransaction().commit();
		session1.close();

		System.out.println("-------------------------------");
	}

结果如下:

Hibernate: select department0_.id as id0_0_, department0_.dept_version as dept2_0_0_, department0_.name as name0_0_ from T_Department department0_ where department0_.id=?
Department [deptId=2, deptName=woqu]
Hibernate: select emps0_.deptId as deptId0_1_, emps0_.id as id1_, emps0_.id as id1_0_, emps0_.emp_version as emp2_1_0_, emps0_.name as name1_0_, emps0_.salary as salary1_0_, emps0_.deptId as deptId1_0_ from T_Employee emps0_ where emps0_.deptId=?
[Employee [empId=3, empName=TO_T_, salary=4]]
-------------------------------
Department [deptId=2, deptName=woqu]
[Employee [empId=3, empName=TO_T_, salary=4]]
Department [deptId=2, deptName=woqu]
[Employee [empId=3, empName=TO_T_, salary=4]]
-------------------------------


分享文章:(20)Hibernate二级缓存
浏览路径:http://abwzjs.com/article/pcsohg.html