hibernate之缓存

来源:互联网 发布:农村淘宝报名网站报名 编辑:程序博客网 时间:2024/05/16 10:41

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,mapvalue就是实体对象,所以一级缓存缓存的是实体对象,不能缓存属性。

    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的二级缓存。其对系统性能的改善往往立竿见影。下篇我就来介绍一下二级缓存。

0 0
原创粉丝点击