hibernate 全面学习 【hibernate 缓存学习 】

hibernate 缓存分为一级缓存和二级缓存,及查询缓存

hinbernate 一级缓存

1、一级缓存很短,和session的生命周期一致,随着session的关闭而消失
   *load/get/iterate(查询实体对象)可以使用缓存数据
2、一级缓存它缓存的是实体对象  
3、如果管理缓存,如session.clear()/session.evict()
4、如何避免一次性大批量实体数据插入内存溢出的问题?
  *先执行flush,在用clear清除缓存

hibernate 二级缓存

定义步骤:
1、打开缓存,在hibernate.cfg.xm中加入:
<property name="hibernate.cache.use_second_level_cache">true</property>

2、指定缓存策略提供商,在hibernate.cfg.xm中加入:
<property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>

3、拷贝echcahe.xml到src下,可以针对不同的策略配置缓存

4、指定那些类使用缓存(两种方式)
  * 在hibernate.cfg.xml
  * 在映射文件中

二级缓存中存储的也是实体对象,他们都属于SessionFactory级别,
是全局的,伴随SessionFactory的生命周期存在和消亡

需要了解一级缓存和二级缓存的交互模式(CacheMode)


hibernate查询缓存

配置:
  在hibernate.cfg.xml文件中加入:<property name="hibernate.cache.use_query_cache">true</property>
 
1、针对普通属性结果集的缓存
2、对是实体对象的结果集,只缓存id
3、使用查询缓存,需要打开查询缓存,并且在调用list方法之前需要显示的调用query.setCacheable(true);

一级缓存

import java.io.Serializable;

import org.hibernate.Session;

import junit.framework.TestCase;

public class CacheLevel1Test extends TestCase {

	/**
	 * 发出两次load查询
	 *
	 */	
	public void testCache1() {
		Session session = null;
		try {
			session = HibernateUtils.getSession();
			Student student = (Student)session.load(Student.class, 1);
			System.out.println("学生姓名:" + student.getName());
			
			//因为有一级缓存,load方法使用一级缓存,所以本次查询不再发出sql
			student = (Student)session.load(Student.class, 1);
			System.out.println("学生姓名:" + student.getName());
			
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
			HibernateUtils.closeSession(session);
		}
	}
	
	/**
	 * 发出两次get查询
	 *
	 */	
	public void testCache2() {
		Session session = null;
		try {
			session = HibernateUtils.getSession();
			Student student = (Student)session.get(Student.class, 1);
			System.out.println("学生姓名:" + student.getName());
			
			//因为有一级缓存,get方法使用一级缓存,所以本次查询不再发出sql
			student = (Student)session.get(Student.class, 1);
			System.out.println("学生姓名:" + student.getName());
			
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
			HibernateUtils.closeSession(session);
		}
	}
	
	/**
	 * 发出两次iterate查询实体对象
	 *
	 */
	public void testCache3() {
		Session session = null;
		try {
			session = HibernateUtils.getSession();
			Student student = (Student)session.createQuery("from Student where id=1").iterate().next();
			System.out.println("学生姓名:" + student.getName());
			
			//因为有一级缓存,iterate方法使用一级缓存,发出查询id的sql,不再发出查询实体对象的sql
			student = (Student)session.createQuery("from Student where id=1").iterate().next();
			System.out.println("学生姓名:" + student.getName());
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
			HibernateUtils.closeSession(session);
		}
	}

	/**
	 * 发出两次iterate查询普通属性
	 *
	 */
	public void testCache4() {
		Session session = null;
		try {
			session = HibernateUtils.getSession();
			String name = (String)session.createQuery("select name from Student where id=1").iterate().next();
			System.out.println("学生姓名:" + name);
			
			//Iterate查询普通结果集,一级缓存不会缓存,它也不会发出查询id的sql
			name = (String)session.createQuery("select name from Student where id=1").iterate().next();
			System.out.println("学生姓名:" + name);
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
			HibernateUtils.closeSession(session);
		}
	}
	
	/**
	 * 打开两次session,调用load测试
	 *
	 */
	public void testCache5() {
		Session session = null;
		try {
			session = HibernateUtils.getSession();
			Student student = (Student)session.load(Student.class, 1);
			System.out.println("学生姓名:" + student.getName());
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
			HibernateUtils.closeSession(session);
		}
		
		//打开第二个session
		try {
			session = HibernateUtils.getSession();
			//会发出sql,session间是不能共享一级缓存数据的
			//因为它会伴随session的生命周期存在和消亡
			Student student = (Student)session.load(Student.class, 1);
			System.out.println("学生姓名:" + student.getName());
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
			HibernateUtils.closeSession(session);
		}		
	}
	
	/**
	 * 先执行save,再执行load进行测试
	 *
	 */
	public void testCache6() {
		Session session = null;
		try {
			session = HibernateUtils.getSession();
			session.beginTransaction();
			Student student = new Student();
			student.setName("张三");
			Serializable id = session.save(student);
			
			//因为save会将实体对象的数据缓存到session中
			//所以再次查询相同数据,不会发出sql
			Student newStudent = (Student)session.load(Student.class, id);
			System.out.println("学生姓名:" + newStudent.getName());
			session.getTransaction().commit();
		}catch(Exception e) {
			e.printStackTrace();
			session.getTransaction().rollback();
		}finally {
			HibernateUtils.closeSession(session);
		}
	}
	
	/**
	 * 执行session.clear()或session.evict()方法后,再调用load 
	 */
	public void testCache7() {
		Session session = null;
		try {
			session = HibernateUtils.getSession();
			Student student = (Student)session.load(Student.class, 1);
			System.out.println("学生姓名:" + student.getName());
			
			//管理session缓存(一级缓存机制无法取消的,但可以管理缓存,如:clear,evict方法)
			session.evict(student);
			//session.clear();
			
			//发出sql,因为缓存中的student实体类,已经被逐出
			student = (Student)session.load(Student.class, 1);
			System.out.println("学生姓名:" + student.getName());
			
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
			HibernateUtils.closeSession(session);
		}
	}
	
	/**
	 * 向数据库中插入10000学生数据
	 *
	 */
	public void testCache8() {
		Session session = null;
		try {
			session = HibernateUtils.getSession();
			session.beginTransaction();
			for (int i = 0; i < 10000; i++) {
				Student student = new Student();
				student.setName("Student_" + i);
				session.save(student);
				
				//每100条数据就强制session将数据持久化
				//同时清空缓存,以避免在大量的数据下,造成内存溢出
				if ( i % 100 == 0) {
					session.flush();
					session.clear();
				}
			}
			session.getTransaction().commit();
		}catch(Exception e) {
			e.printStackTrace();
			session.getTransaction().rollback();
		}finally {
			HibernateUtils.closeSession(session);
		}		
	}
}


二级缓存测试
package com.bjsxt.hibernate;

import java.io.Serializable;

import org.hibernate.CacheMode;
import org.hibernate.Session;
import org.hibernate.SessionFactory;

import junit.framework.TestCase;

public class CacheLevel2Test extends TestCase {

	/**
	 * 打开两次session,调用load测试
	 *
	 */
	public void testCache1() {
		Session session = null;
		try {
			session = HibernateUtils.getSession();
			Student student = (Student)session.load(Student.class, 1);
			System.out.println("学生姓名:" + student.getName());
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
			HibernateUtils.closeSession(session);
		}
		
		//打开第二个session
		try {
			session = HibernateUtils.getSession();
			
			//因为打开了二级缓存,所以本次查询不会发出sql
			Student student = (Student)session.load(Student.class, 1);
			System.out.println("学生姓名:" + student.getName());
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
			HibernateUtils.closeSession(session);
		}		
	}

	/**
	 * 调用了次load,第一次调用完成后,清除sessionFactory中的二级缓存数据,
	 * 再开启一个session,调用load
	 *
	 */
	public void testCache2() {
		Session session = null;
		try {
			session = HibernateUtils.getSession();
			Student student = (Student)session.load(Student.class, 1);
			System.out.println("学生姓名:" + student.getName());
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
			HibernateUtils.closeSession(session);
		}
		
		//管理二级缓存
		SessionFactory factory = HibernateUtils.getSessionFactory();
		factory.evict(Student.class);
		
		//打开第二个session
		try {
			session = HibernateUtils.getSession();
			
			//因为二级缓存已经被清空,所以本次查询将发出一条新的sql
			Student student = (Student)session.load(Student.class, 1);
			System.out.println("学生姓名:" + student.getName());
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
			HibernateUtils.closeSession(session);
		}		
	}
	
	/**
	 * 调用了次load,第一次调用完成后,清除sessionFactory中的二级缓存数据,
	 * 再开启一个session,调用load
	 *
	 */
	public void testCache3() {
		Session session = null;
		try {
			session = HibernateUtils.getSession();
			
			//GET的CahceMode,使得session指会从sessionFactory中获取数据
			//而不向其中添加数据
			session.setCacheMode(CacheMode.GET);

			Student student = (Student)session.load(Student.class, 1);
			System.out.println("学生姓名:" + student.getName());
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
			HibernateUtils.closeSession(session);
		}
		
		//打开第二个session
		try {
			session = HibernateUtils.getSession();
			
			//因为二级缓存中没有数据,所以发出sql
			Student student = (Student)session.load(Student.class, 1);
			System.out.println("学生姓名:" + student.getName());
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
			HibernateUtils.closeSession(session);
		}
		
		//打开第三个session
		try {
			
			session = HibernateUtils.getSession();
			session.setCacheMode(CacheMode.PUT);
			//不会读数据,所以发出sql
			Student student = (Student)session.load(Student.class, 1);
			System.out.println("学生姓名:" + student.getName());
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
			HibernateUtils.closeSession(session);
		}
		
		//打开第四个session
		try {
			session = HibernateUtils.getSession();
			//不会发出sql
			Student student = (Student)session.load(Student.class, 1);
			System.out.println("学生姓名:" + student.getName());
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
			HibernateUtils.closeSession(session);
		}
		
	}
}


查询缓存

package com.bjsxt.hibernate;

import java.io.Serializable;
import java.util.Iterator;
import java.util.List;

import org.hibernate.CacheMode;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;

import junit.framework.TestCase;

public class QueryCacheTest extends TestCase {

	/**
	 *  执行两次query
	 * 
	 */
	public void testCache1() {
		Session session = null;
		try {
			session = HibernateUtils.getSession();
			Query query = session.createQuery("select s.name from Student s");
			query.setCacheable(true);
			
			List names = query.list();
			for (Iterator iter = names.iterator(); iter.hasNext();) {
				String name = (String)iter.next();
				System.out.println(name);
			}
			System.out.println("----------------------------------------------------");
			//不再发出sql,因为启用了查询缓存
			query = session.createQuery("select s.name from Student s");
			query.setCacheable(true);
			names = query.list();
			for (Iterator iter = names.iterator(); iter.hasNext();) {
				String name = (String)iter.next();
				System.out.println(name);
			}
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
			HibernateUtils.closeSession(session);
		}
	}
	
	/**
	 * 执行两次query,第二个query新open一个session 
	 *
	 */
	public void testCache2() {
		Session session = null;
		try {
			session = HibernateUtils.getSession();
			Query query = session.createQuery("select s.name from Student s");
			query.setCacheable(true);
			List names = query.list();
			for (Iterator iter = names.iterator(); iter.hasNext();) {
				String name = (String)iter.next();
				System.out.println(name);
			}
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
			HibernateUtils.closeSession(session);
		}

		try {
			session = HibernateUtils.getSession();
			System.out.println("----------------------------------------------------");
			//不再发出sql,因为查询缓存的生命周期和session无关
			Query query = session.createQuery("select s.name from Student s");
			query.setCacheable(true);
			List names = query.list();
			for (Iterator iter = names.iterator(); iter.hasNext();) {
				String name = (String)iter.next();
				System.out.println(name);
			}
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
			HibernateUtils.closeSession(session);
		}
	}

	/**
	 * 采用query.iterate测试
	 *
	 */
	public void testCache3() {
		Session session = null;
		try {
			session = HibernateUtils.getSession();
			Query query = session.createQuery("select s.name from Student s");
			query.setCacheable(true);
			
			Iterator iter = query.iterate();
			while (iter.hasNext()) {
				String name = (String)iter.next();
				System.out.println(name);
			}
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
			HibernateUtils.closeSession(session);
		}
		
		try {
			System.out.println("----------------------------------------------------------");
			session = HibernateUtils.getSession();
			Query query = session.createQuery("select s.name from Student s");
			query.setCacheable(true);
			
			//query.iterate()操作不会使用查询缓存
			//!!!查询缓存只对query.list()操作有效!
			Iterator iter = query.iterate();
			while (iter.hasNext()) {
				String name = (String)iter.next();
				System.out.println(name);
			}
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
			HibernateUtils.closeSession(session);
		}
	}
	
	/**
	 * 1、使用查询缓存
	 * 2、查询实体对象数据
	 * 3、把二级缓存关闭
	 *
	 */
	public void testCache4() {
		Session session = null;
		try {
			session = HibernateUtils.getSession();
			Query query = session.createQuery("select s from Student s");
			query.setCacheable(true);
			List students = query.list();
			for (Iterator iter = students.iterator(); iter.hasNext();) {
				Student student = (Student)iter.next();
				System.out.println(student.getName());
			}
			System.out.println("-------------------------------------------------");
			query = session.createQuery("select s from Student s");
			query.setCacheable(true);
			students = query.list();
			for (Iterator iter = students.iterator(); iter.hasNext();) {
				Student student = (Student)iter.next();
				System.out.println(student.getName());
			}
			
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
			HibernateUtils.closeSession(session);
		}
		
//		try {
//			System.out.println("-------------------------------------------------");
//			session = HibernateUtils.getSession();
//			//将会发出n条查询语句,因为二级缓存被关闭,而查询缓存中的数据只是实体对象的id
//			//list操作会根据这些id依次到数据库中查找
//			Query query = session.createQuery("select s from Student s");
//			query.setCacheable(true);
//			List students = query.list();
//			for (Iterator iter = students.iterator(); iter.hasNext();) {
//				Student student = (Student)iter.next();
//				System.out.println(student.getName());
//			}
//		}catch(Exception e) {
//			e.printStackTrace();
//		}finally {
//			HibernateUtils.closeSession(session);
//		}
		
	}
}

你可能感兴趣的:(sql,Hibernate,cache,JUnit,配置管理)