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 ...
随机推荐
- 二叉树结构 codevs 1029 遍历问题
codevs 1029 遍历问题 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 我们都很熟悉二叉树的前序.中序.后序遍 ...
- 怎么在ZBrush中通过遮罩得到子物体
ZBrush® 中通过遮罩为模型添加子物体的方法简单且方便,我们可以通过按住Ctrl键绘制遮罩结合相关命令创建具有抽出厚度的模型提取出作为子物体附在模型表面.本文将详细介绍在Zbrush中如何通过遮罩 ...
- two sum - leetcode
Given an array of integers, return indices of the two numbers such that they add up to a specific ta ...
- Unity3D开发之搭建Mac OS开发环境
运行图 首先上几张图 IOS模拟器 坚屏 横屏 打包任务 摸索了一上午,才搞定在模拟器中运行.至于在Iphone真机中运行,虽然有开发者证书,目前还没在Xcode中配置好. 我今天第一次接触并使用MA ...
- java9-3 返回类型
1. 返回值类型 基本类型:(基本类型简单) 引用类型: 类:返回的是该类的对象 class Student2 { public void study() { System.out.println(& ...
- VS代码片段(snippet)创作工具——Snippet Editor(转)
原文:http://blog.csdn.net/oyi319/article/details/5605502 从Visual Studio 2005开始,IDE支持代码片段.代码片段以代码缩写和TAB ...
- Http请求中POST与GET的区别——前端面试
一.原理区别 Http定义了与服务器交互的方法,其中最基本的四种是:GET,POST,PUT,DELETE,正对应着对资源的查,改,增,删.URL的全称是资源描述符,我们可以这样认为,一个URL地址, ...
- uart串口的调试学习
用FPGA设计了数据接收和发送模块,FIFO模块,此处FIFO调用的是Show-ahead模式,在下一篇博客中将会分析这个问题. 用串口调试工具发送数据,数据接收模块将接收到的串行数据转换为并行数据( ...
- [转]php返回json数据中文显示的问题
转自 : http://blog.csdn.net/superbirds/article/details/8091910 解决方法: <?php function Notice(){ ...
- php基础05:常量
<?php // 1.PHP 常量介绍 // 常量是单个值的标识符(名称).在脚本中无法改变该值.有效的常量名以字符或下划线开头(常量名称前面没有 $ 符号). // 2设置 PHP 常量 // ...