您现在的位置: 万盛学电脑网 >> 程序编程 >> 网络编程 >> 编程语言综合 >> 正文

语言教程学堂:hibernate缓存机制详细分析

作者:佚名    责任编辑:admin    更新时间:2022-06-22

在本篇随笔里将会分析一下hibernate的缓存机制,包括一级缓存(session级别)、二级缓存(sessionFactory级别)以及查询缓存,当然还要讨论下我们的N+1的问题。

随笔虽长,但我相信看完的朋友绝对能对hibernate的 N+1问题以及缓存有更深的了解。

一、N+1问题

首先我们来探讨一下N+1的问题,我们先通过一个例子来看一下,什么是N+1问题:

list()获得对象:

复制代码
       /** * 此时会发出一条sql,将30个学生全部查询出来 */ List<Student> ls = (List<Student>)session.createQuery("from Student") .setFirstResult(0).setMaxResults(30).list(); Iterator<Student> stus =ls.iterator(); for(;stus.hasNext();) { Student stu = (Student)stus.next(); System.out.println(stu.getName()); }
复制代码

如果通过list()方法来获得对象,毫无疑问,hibernate会发出一条sql语句,将所有的对象查询出来,这点相信大家都能理解

Hibernate: select student0_.id as id2_, student0_.name as name2_, student0_.rid as rid2_, student0_.sex as sex2_ from t_student student0_ limit ?

那么,我们再来看看iterator()这种情况

iterator()获得对象

复制代码
       /** * 如果使用iterator方法返回列表,对于hibernate而言,它仅仅只是发出取id列表的sql * 在查询相应的具体的某个学生信息时,会发出相应的SQL去取学生信息 * 这就是典型的N+1问题 * 存在iterator的原因是,有可能会在一个session中查询两次数据,如果使用list每一次都会把所有的对象查询上来 * 而是要iterator仅仅只会查询id,此时所有的对象已经存储在一级缓存(session的缓存)中,可以直接获取 */ Iterator<Student> stus = (Iterator<Student>)session.createQuery("from Student") .setFirstResult(0).setMaxResults(30).iterate(); for(;stus.hasNext();) { Student stu = (Student)stus.next(); System.out.println(stu.getName()); }
复制代码

在执行完上述的测试用例后,我们来看看控制台的输出,看会发出多少条 sql 语句:

复制代码
Hibernate: select student0_.id as col_0_0_ from t_student student0_ limit ?Hibernate: select student0_.id as id2_0_, student0_.name as name2_0_, student0_.rid as rid2_0_, student0_.sex as sex2_0_ from t_student student0_ where student0_.id=?