Hibernate-一级缓存session
hibernate提供的一级缓存
hibernate是一个线程对应一个session,一个线程可以看成一个用户。也就是说session级缓存(一级缓存)只能给一个线程用,别的线程用不了,一级缓存就是和线程绑定了。
hibernate一级缓存生命周期很短,和session生命周期一样,一级缓存也称session级的缓存或事务级缓存。
如果tb事务提交或回滚了,我们称session就关闭了,生命周期结束了。
实例:
(hibernate使用load查询)
//同一个session中,发出两次load方法查询
Student student = (Student)session.load(Student.class, 1);
System.out.println("student.name=" + student.getName());
//不会发出查询语句,load使用缓存
student = (Student)session.load(Student.class, 1);
System.out.println("student.name=" + student.getName());
第二次查询第一次相同的数据,第二次load方法就是从缓存里取数据,不会发出sql语句到数据库里查询。
(hibernate使用get查询)
//同一个session,发出两次get方法查询
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());
第二次查询第一次相同的数据,第二次不会发出sql语句查询数据库,而是到缓存里取数据。
(hibernate使用iterate查询)
//同一个session,发出两次iterate查询实体对象
Iterator iter = session.createQuery("from Student s where s.id<5").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<5").iterate();
while (iter.hasNext()) {
Student student = (Student)iter.next();
System.out.println(student.getName());
}
第二次查询第一次相同的数据,第二次不会发出sql语句查询数据库,而是到缓存里取数据。
说到iterater查询就要立刻想起:iterater查询在没有缓存的情况下会有N+1的问题。
执行上面代码查看控制台的sql语句,第一次iterate查询会发出N+1条sql语句,第一条sql语句查询所有的id,然后根据id查询实体对象,有N个id就发出N条语句查询实体。
第一次发出N+1条sql语句,第二次还是发出了N+1条sql语句。因为一级缓存只缓存实体对象,tb不会缓存普通属性,所以第二次还是发出sql查询语句。
-----------
(测试两个session之间不能共享缓存数据)
//两个session,每个session发出一个load方法查询实体对象
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Student student = (Student)session.load(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调用load方法
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Student student = (Student)session.load(Student.class, 1);
//会发出查询语句,session间不能共享一级缓存数据
//因为他会伴随着session的消亡而消亡
System.out.println("student.name=" + student.getName());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
第一个session的load方法会发出sql语句查询实体对象,第二个session的load方法也会发出sql语句查询实体对象。因为session间不能共享一级缓存的数据,所以第二个session的load方法查询相同的数据还是要到数据库中查询,因为它找不到第一个session里缓存的数据。
(session的save支持缓存)
//同一个session,先调用save方法再调用load方法查询刚刚save的数据
Student student = new Student();
student.setName("张三");
//save方法返回实体对象的id
Serializable id = session.save(student);
student = (Student)session.load(Student.class, id);
//不会发出查询语句,因为save支持缓存
System.out.println("student.name=" + student.getName());
先save保存实体对象,再用load方法查询刚刚save的实体对象,则load方法不会发出sql语句到数据库查询的,而是到缓存里取数据,因为save方法也支持缓存。当然前提是同一个session。
大批量的数据添加(内存的溢出)
for (int i=0; i<100; i++) {
Student student = new Student();
student.setName("张三" + i);
session.save(student);
//每20条更新一次
if (i % 20 == 0) {
session.flush();
//清除缓存的内容
session.clear();
}
}
大批量数据添加时,会造成内存溢出的,因为save方法支持缓存,每save一个对象就往缓存里放,如果对象足够多内存肯定要溢出。一般的做法是先判断一下save了多少个对象,如果save了20个对象就对缓存手动的清理缓存,这样就不会造成内存溢出。
注意:清理缓存前,要手动调用flush方法同步到数据库,否则save的对象就没有保存到数据库里。
注意:大批量数据的添加还是不要使用hibernate,这是hibernate弱项。可以使用jdbc(速度也不会太快,只是比hibernate好一点),或者使用工具产品来实现,比如oracle的Oracle SQL Loader,导入数据特别快。
Hibernate-一级缓存session的更多相关文章
- Hibernate一级缓存Session和对象的状态
建议看原文:https://blog.csdn.net/qq_42402854/article/details/81461496 一.session简介 首先,SessionFactor ...
- hibernate一级缓存
理解 Hibernate 一级缓存 Hibernate 一级缓存默认是打开,不需要任何的配置.实际上,你无法强制禁止它的使用. 如果你理解了一级缓存实际上和会话是关联的,就很容易理解一级缓存.总所周知 ...
- Hibernate一级缓存(基于查询分析)
首先我们应该弄清什么是hibernate缓存:hibernate缓存是指为了降低应用程序对物理数据源的访问频次,从而提高应用程序的运行性能的一种策略.我们要将这个跟计算机内存或者cpu的缓存区分开. ...
- hibernate一级缓存及对象的状态
hibernate中实体类对象的状态 在hibernate中实体类对象有三种状态 (1)瞬时态(临时态) 瞬时态:即我们自己创建一个对象,还没有保存到数据库就叫临时态,其实也可以说是对像没有id值,跟 ...
- Hibernate一级缓存(补)
------------------siwuxie095 什么是缓存 缓存是介于应用程序和永久性数据存储源(如:硬盘上的 ...
- Hibernate一级缓存测试分析
Hibernate 一级缓存测试分析 Hibernate的一级缓存就是指Session缓存,此Session非http的session会话技术,可以理解为JDBC的Connection,连接会话,Se ...
- 转载 hibernate一级缓存和二级缓存的区别
文章来源:http://blog.csdn.net/defonds/article/details/2308972 hibernate一级缓存和二级缓存的区别 缓存是介于应用程序和物理数据源之 ...
- Hibernate一级缓存和三种状态
Hibernate一级缓存又称session缓存,生命周期很短,跟session生命周期相同. 三种状态:1.transient(瞬时态):刚new出来的对象,既不在数据库中,也不在session管理 ...
- hibernate - 一级缓存和三种状态解析
转载自:http://www.cnblogs.com/whgk/p/6103038.html 一.一级缓存和快照 什么是一级缓存呢? 很简单,每次hibernate跟数据库打交道时,都是通过sessi ...
- hibernate笔记--缓存机制之 一级缓存(session缓存)
一级缓存: 又称为session缓存,它和session生命周期相同,周期非常短.是事务级别的缓存: 还是以Book和Category这两个表为例,我们用代码观察一个缓存的存在: 假设现在我要去查询i ...
随机推荐
- 类似区间计数的种类并查集两题--HDU 3038 & POJ 1733
1.POJ 1733 Parity game Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 5744 Accepted: ...
- uGUI练习(三) KeyBoard Navigation
练习目标 练习通过键盘在按钮或其它Selectable类型组件上导航 步骤 创建一排的Button,及一个右边的Button 2.查看Button的属性里有一栏下拉列表Navigation,默认选择的 ...
- kvm虚拟机时间修改
在虚拟化环境中,虚拟机在长时间运行过程中,时间会变慢,通常的作法是配置ntpdate定时与时间服务器进行时间同步的计划任务.KVM虚拟机默认采用utc时间,需要专门修改,以及考虑kvm时间同步问题.1 ...
- Wordpress 3.5.1的debug流水账
一个合作网站是基于Wordpress做的, 不能正常使用FeedWordPress这个插件, 对方没有开发者, 只有一个类似于美工和编辑的人, 因为我在本地使用同样的版本(Wordpress 3.5. ...
- 1017. A除以B (20)
本题要求计算A/B,其中A是不超过1000位的正整数,B是1位正整数.你需要输出商数Q和余数R,使得A = B * Q + R成立. 输入格式: 输入在1行中依次给出A和B,中间以1空格分隔. 输出格 ...
- CENTOS7 添加自定义快捷键(启动TERMINAL,显示桌面等)
centos7中不自带启动终端的快捷键,可以自定义添加. 点击右上角的用户名,点击设置,在设置面板点击键盘,选择快捷键选项卡进入快捷键设置界面. 点击“+”添加快捷键.名称自定义(如"启动终 ...
- 学习Shell脚本编程(第3期)_在Shell程序中使用的参数
位置参数 内部参数 如同ls命令可以接受目录等作为它的参数一样,在Shell编程时同样可以使用参数.Shell程序中的参数分为位置参数和内部参数等. 3.1 位置参数 由系统提供的参数称为位置参数.位 ...
- 通过数据库方式访问excel 2007及其以后(xlsx)文件的连接字符串
sqlconn.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=D:\test3.xls;Extended Properties=&q ...
- 20135220谈愈敏Linux Book_17
第17章 设备与模块 关于设备驱动和设备管理的四种内核成分: 设备类型:在所有 Unix 系统中为了统一普通设备的操作所采用的分类. 模块: Linux 内核中用于按需加载和卸载目标码的机制. 内核对 ...
- 错误C2665: “AfxMessageBox”: 2 个重载中没有一个可以转换所有参数类型
第一种方法: AfxMessageBox( "Simple message box. ");如果先定义一个CString 变量,再赋值就没问题CString sTe ...