码迷,mamicode.com
首页 > Web开发 > 详细

hibernate之缓存

时间:2015-08-01 01:13:28      阅读:180      评论:0      收藏:0      [点我收藏+]

标签:

1.Java中的缓存是指的是一组用于提高IO性能的内存地址,它位于JVM中,存储在内存或者磁盘中。

2.  为什么要用Hibernate缓存?

       Hibernate是一个持久层框架,经常访问物理数据库。为了降低应用程序对物理数据源访问的频次,从而提高应用程序的运行性能。缓存内的数据时对物理数据源中的数据的赋值,应用程序在运行时从缓存读写数据,如果缓存中不存在,才会去访问数据库。

3.Hibernate缓存分类

(1) 一级缓存:

    是一个线程对应一个session,一个线程可以看成一个用户。也就是说session级缓存只能给一个线程用,别的线程用不了,大家不能共享,总之,一级缓存就是和线程绑定了。一级缓存的生命周期很短,和session生命周期一样,一级缓存也称session级的缓存或事务级的缓存。如果session关闭了,生命九期也就结束了。

(2) 二级缓存:

    二级缓存也称为进程级的缓存或sessionFactory级的缓存。二级缓存可以被所有的session共享。二级缓存的生命周期和SessionFactory的生命周期一致,SessionFactory可以管理二级缓存。

(3)查询缓存:

    查询缓存是缓存普通属性结果集的,对实体对象的结果集会缓存id。当关联的表发生修改,查询缓存的生命周期就结束了。

4. 一级缓存

    对于Hibernate一级缓存时默认就有的,并且不能卸载。一级缓存的内部结构就是一个map<id,object>,mapkey就是id,map value就是实体对象,所以一级缓存缓存的是实体对象,不能缓存属性。

    hibernate是一个线程对应一个session,一个线程可以看成一个用户。也就是说session级缓存(一级缓存)只能给一个线程用,别的线程用不了,一级缓存就是和线程绑定了。hibernate一级缓存生命周期很短,和session生命周期一样,一级缓存也称session级的缓存或事务级缓存。如果tb事务提交或回滚了,我们称session就关闭了,生命周期结束了。

下面我们来看写一下测试代码:

classes类:

package com.lsh.hibernate;

import java.util.Set;

public class Classes {

	private int id;
	
	private String name;
	
	private Set students;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Set getStudents() {
		return students;
	}

	public void setStudents(Set students) {
		this.students = students;
	}
}

Junit测试类:

package com.lsh.hibernate;

import java.io.Serializable;
import java.util.Iterator;
import org.hibernate.Session;
import junit.framework.TestCase;

public class CacheTest extends TestCase {

	/**
	 * 在同一个session中发出两次load查询
	 */
	public void testCache1(){
		Session session =null;
		try {
			session =HibernateUtils.getSession();
			session.beginTransaction();
			Student student =(Student)session.load(Student.class, 10);
			System.out.println("student.name=" + student.getName());
			
			//不会发出查询语句,load使用缓存
			student=(Student)session.load(Student.class, 10);
			System.out.println("student.name=" +student.getName());
			
			session.getTransaction().commit();
		} catch (Exception e) {
			e.printStackTrace();
			session.getTransaction().rollback();
		}finally{
			HibernateUtils.closeSession(session);
		}
	}
	
	/**
	 * 在同一个session中发出两次get查询
	 */
	public void testCache2(){
		Session session =null;
		try {
			session =HibernateUtils.getSession();
			session.beginTransaction();
			Student student =(Student)session.get(Student.class, 1);
			System.out.println("student.name=" + student.getName());
			
			//不会发出查询语句,get使用缓存
			student=(Student)session.get(Student.class, 1);
			System.out.println("student.name=" +student.getName());
			
			session.getTransaction().commit();
		} catch (Exception e) {
			e.printStackTrace();
			session.getTransaction().rollback();
		}finally{
			HibernateUtils.closeSession(session);
		}
	}
	
	/**
	 * 在同一个session中发出两次iterate查询,查询实体对象
	 */
	public void testCache3(){
		Session session =null;
		try {
			session =HibernateUtils.getSession();
			session.beginTransaction();
			Iterator iter = session.createQuery("from Student s where s.id<10").iterate();
		while (iter.hasNext()) {
			Student student = (Student) iter.next();
			System.out.println(student.getName());
			
		}
		
		System.out.println("_______________________________");
		
		//它会发出查询id的语句,但不会发出根据id查询学生的语句,因为iterate使用缓存
		iter=session.createQuery("from Student s where s.id<10").iterate();
		while (iter.hasNext()) {
			Student student = (Student) iter.next();
			System.out.println(student.getName());
			
		}
			session.getTransaction().commit();
		} catch (Exception e) {
			e.printStackTrace();
			session.getTransaction().rollback();
		}finally{
			HibernateUtils.closeSession(session);
		}
	}
	
	/**
	 * 在两个session中发出iterate查询,查询普通属性
	 */
	public void testCache4(){
		Session session =null;
		try {
			session =HibernateUtils.getSession();
			session.beginTransaction();
			Iterator iter = session.createQuery("select s.name from Student s where s.id<5").iterate();
		while (iter.hasNext()) {
			String  name = (String) iter.next();
			System.out.println(name);
			
		}
		
		System.out.println("_______________________________");
		
		//iterate查询普通属性,一级缓存不会缓存,所以发出查询语句
		//一级缓存是缓存实体对象的
		iter=session.createQuery(" select s.name from Student s where s.id<5").iterate();
		while (iter.hasNext()) {
			String  name = (String) iter.next();
			System.out.println(name);
			
		}
			session.getTransaction().commit();
		} catch (Exception e) {
			e.printStackTrace();
			session.getTransaction().rollback();
		}finally{
			HibernateUtils.closeSession(session);
		}
	}
	
	/**
	 * 在同二个session中发出load查询
	 */
	public void testCache5(){
		Session session =null;
		try {
			session =HibernateUtils.getSession();
			session.beginTransaction();
			Student student =(Student)session.load(Student.class, 10);
			System.out.println("student.name=" + student.getName());
			
			session.getTransaction().commit();
		} catch (Exception e) {
			e.printStackTrace();
			session.getTransaction().rollback();
		}finally{
			HibernateUtils.closeSession(session);
		}
		
		try {
			session =HibernateUtils.getSession();
			session.beginTransaction();
				
			//会发出查询语句,session间不能共享一级缓存数据
			//因为他会伴随着session的消亡而消亡
			Student student =(Student)session.load(Student.class, 10);
			System.out.println("student.name=" + student.getName());
			
			session.getTransaction().commit();
		} catch (Exception e) {
			e.printStackTrace();
			session.getTransaction().rollback();
		}finally{
			HibernateUtils.closeSession(session);
		}
	}
	
	/**
	 * 在同一个session中先调用save,再调用load查询刚刚save的数据
	 */
	public void testCache6(){
		Session session=null;
		try {
			session=HibernateUtils.getSession();
			session.beginTransaction();
			Student student =new Student();
			student.setName("张三");
			Serializable id =session.save(student);
			student=(Student)session.load(Student.class, id);
			
			//不会发出查询语句,因为save支持缓存
			System.out.println("student.name=" + student.getName());
			session.getTransaction().commit();
			
		} catch (Exception e) {
			e.printStackTrace();
			session.getTransaction().rollback();
		}finally{
			HibernateUtils.closeSession(session);
		}
	}
	
	/**
	 * 大批量的数据添加,如果放大量的缓存会溢出,定期清理一下缓存
	 */
	public void testCache7(){
		Session session=null;
		try {
			session=HibernateUtils.getSession();
			session.beginTransaction();
			for (int i = 0; i <100; i++) {
				Student student =new Student();
				student.setName("张三" +i);
				session.save(student);
				if (i%20==0) {
					//执行sql语句,相当于把这些缓存全部保存到数据库中了
					session.flush();
					//清楚缓存的内容
					session.clear();
				}
			}
			session.getTransaction().commit();
		} catch (Exception e) {
			e.printStackTrace();
			session.getTransaction().rollback();
		}finally{
			HibernateUtils.closeSession(session);
		}
	}
}

下面是对上面代码的提取总结:

技术分享

    因为Session的生命周期往往很短,存在于Session内部的第一集最快缓存的生命周期也是很短的,所以一级缓存的命中率很低的。其对系统性能的改善也是很有限的。当然,这个session内部缓存的主要作用是保持session内部数据状态同步,并非是hibernate为了大幅提高系统性能所提供的。

    为了提高使用hibernate的性能,除了常规的一些需要注意的方法,如:用延迟加载、迫切外链接、查询过滤等以外,还需要配置hibernate的二级缓存。其对系统性能的改善往往立竿见影。下篇我就来介绍一下二级缓存。

版权声明:本文为博主原创文章,未经博主允许不得转载。

hibernate之缓存

标签:

原文地址:http://blog.csdn.net/lvshihua/article/details/47177209

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!