Hibernate基础学习(三)—Session
一、概述
Session接口是Hibernate向应用程序提供的操纵数据库最主要的接口,它提供了基本的保存、更新、删除和加载Java对象的方法。
Session具有一个缓存,位于缓存中的对象称为持久化对象,它和数据库相关记录对应。
Session能够在某些时间点按照缓存中对象的变化来执行相关SQL语句,来同步更新数据库,这一过程称为清理缓存(flush)。
二、Session的缓存
1.理解
如果希望一个Java对象A一直处于生命周期中,就必须保证至少有一个变量引用它,或者可以从其他处于生命周期中的对象B导航到这个对象A,比如在对象B的Java集合属性存放对象A的引用。在Session接口的实现中包含了一系列的Java集合,这些Java集合构成了Session的缓存。只要Session实例没有结束生命周期,存放在它缓存中的对象也不会结束生命周期。
当Session的save()方法持久化一个Customer对象时,Customer对象被加入到Session缓存中,以后即使应用程序中的引用变量不再引用Customer对象,只要Session的缓存没有被清空,Customer对象仍然处于生命周期中。
当Session的get()方法试图从数据库中加载一个Customer对象时,Session先判断缓存中是否已经存在这个Customer对象,如果存在就不需要再到数据库中检索,而直接从缓存中获取这个Customer对象。
- @Test
- public void testSessionCache(){
- Session session = HibernateUtils.getSession();
- //结果是查询了一次数据库,第二次没有查询数据库
- News news1 = (News)session.get(News.class,1);
- System.out.println(news1);
- News news12 = (News)session.get(News.class,1);
- System.out.println(news1);
- }
2.Session缓存的作用
(1)减少访问数据库的频率
应用程序从缓存中读取持久化对象的速度显然要比到数据库中查询的速度要快的多,因此Session的缓存可以提高数据访问的性能。
- //第1次执行Session的get()方法
- News n1 = (News)session.get(News.class,1);
- //第2次执行Session的get()方法
- News n2 = (News)session.get(News.class,1);
- System.out.println(n1 == n2); //true
下图显示第一次执行Session的的get()方法
下图显示了第二次执行Session的get()方法
(2)当缓存中的持久化对象之间存在循环关联关系时,Session会保证不出现访问对象图的死循环,以及死循环引起的JVM堆栈溢出异常。
(3)保证数据库中的相关记录与缓存中的相应对象保持同步。
如下图对象-关系映射建立了表与类之间的静态映射,而Session建立了表与Session缓存中的对象的动态映射。
以下程序先把Customer对象加载到Session缓存中,然后修改Session缓存中Customer对象的属性。
- // 开启事务
- tx = session.beginTransaction();
- Customer c = (Customer)session.get(Customer.class,1);
- c.setName("Jack");
- // 提交事务
- tx.commit();
执行完后,Session中的Customer对象的name属性与Customer表对应记录的name字段值不一致了。
幸运的是,Session在清理缓存时会自动进行脏检查(dirty-check),如果发现Session缓存中的对象与数据库中相应记录不一致,就会根据对象的最新属性去同步更新数据库,在本例中,Session在提交事务之前执行flush()方法清理缓存,即向数据库提交一条update语句,更新数据库中的name字段的值。
3.缓存清理机制
(1)Session如何进行脏检查?
当一个Customer对象被加入到Session缓存中时,Session会为Customer对象的值类型的属性复制一份快照。当Session清理缓存时,会先进行脏检查,即比较Customer对象的当前属性与它的快照来判断Customer对象的属性是否发生了变化,如果发生了变化,就称这个对象为“脏对象”,Session会根据脏对象的最新属性来执行相关SQL语句,从而更新到数据库。
当Session缓存对象的属性每次发生了变化,Session并不会立即执行清理缓存及执行相关SQL语句,而是在特定的时间点才清理缓存,这使得Session能够把几条相关SQL语句合并为一条SQL语句,以便减少访问数据库的次数,从而提高应用程序的数据访问性能。
- tx = session.beginTransaction();
- Customer c = (Customer)session.get(Customer.class,1);
- //当Sesion清理缓存时,不必执行两条update语句,而是执行最后一句
- c.setName("Jack");
- c.setName("Mary");
- tx.commit();
(2)Session清理缓存的时间点
A: 应用程序显式调用Session的flush()方法。
B: 应用程序调用commit()方法时,在内部先执行flush()方法,再向数据库提交事务。
C: 当应用程序执行一些查询(HQL/Criteria)操作时,如果缓存中的持久化对象已经发生了变化,就会先flush,以保证查询结果为最新的状态。
(3)Commit()与flush()方法的区别
flush 执行SQL语句,但不提交事务。
commit 方法先调用flush() 方法,然后提交事务. 意味着提交事务意味着对数据库操作永久保存下来。
三、Hibernate的的三种状态
1.概述
Hibernate有以下三种状态:
临时状态(transient): 刚用new语句创建,还没有被持久化,并且不处于Session的缓存中。
持久化状态(persistent): 已经被持久化,并且处于Session缓存中。
游离状态(detached): 已经被持久化,但不再处于Session缓存中。
2.临时对象的特征
(1)使用代理主键的情况下,OID通常为null。
(2)不在Session的缓存中。
(3)数据库没有相应的记录。
3.持久化对象的特征
(1)OID不为null。
(2)位于Session的缓存中。
(3)持久化对象和数据库的相关记录对应。
(4)Session在flush()缓存时,会根据持久化对象的属性变化,来同步更新数据库。
4.游离对象的特征
(1)OID不为null。
(2)不再处于Session的缓存中。
(3)一般情况下,游离对象是由持久化对象转变而来的,所以数据库还肯存在与它相对应的记录。
5.对象的状态转换图
四、Session的相关API
1.save()和persist()方法
Session的save()方法完成以下操作:
(1)使一个临时对象变为持久化对象。
(2)为对象分配OID。
(3)在flush时,会发送一条insert语句。
注意:
A: 在执行save()方法之前,设置对象的id是无效的。
B: 持久化对象的id是不能修改的,不然会抛异常。
- @Test
- public void testSave(){
- Session session = HibernateUtils.getSession();
- Transaction tx = null;
- try{
- // 开启事务
- tx = session.beginTransaction();
- News news = new News();
- news.setTitle("DDD");
- news.setAuthor("Jack");
- news.setDate(new Date());
- //在save之前设置id是无效的
- news.setId(100);
- System.out.println(news);
- session.save(news);
- System.out.println(news);
- //持久化对象的id是不能修改的,下面这句话报异常
- news.setId(200);
- // 提交事务
- tx.commit();
- }catch(RuntimeException e){
- // 回滚事务
- tx.rollback();
- throw e;
- }finally{
- // 释放资源
- session.close();
- }
- }
persist()方法也会执行insert语句,但是它和save()方法有点区别:
在调用persist()方法之前,若对象有id,则不会执行insert语句,会报异常。
- @Test
- public void testPersist(){
- Session session = HibernateUtils.getSession();
- Transaction tx = null;
- try{
- // 开启事务
- tx = session.beginTransaction();
- News news = new News();
- news.setTitle("CCC");
- news.setAuthor("C");
- news.setDate(new Date());
- news.setId(100);
- System.out.println(news);
- //这句话会抛异常
- session.persist(news);
- System.out.println(news);
- // 提交事务
- tx.commit();
- }catch(RuntimeException e){
- // 回滚事务
- tx.rollback();
- throw e;
- }finally{
- // 释放资源
- session.close();
- }
- }
2.get()和load()方法
Session的get()和load()方法都能根据给定的OID从数据库加载一个持久化对象。
它们有以下区别:
(1)get()使用的是立即检索策略。
load()使用的是延迟检索策略,即load()方法返回的是只要一个id属性的代理对象,只有真正使用该对象时,才会发生SQL语句。
(2)get()如果查询不存在的记录会返回null。
load()如果查询不存在的记录则会抛异常,ObjectNotFoundException。
3.update()方法
Session的update()方法完成以下操作:
(1)把游离对象变为持久化对象。
(2)无论游离对象是否和表一致,都会发生一条update语句。
- News news = new News();
- news.setTitle("CCC");
- session.save(news);
- tx.commit(); //清理缓存,提交事务
- session.close(); //此时news对象变为游离对象
- Session session2 = HibernateUtils.getSession();
- Transaction tx2 = session2.beginTransaction();
- news.setTitle("DDD");
- session2.update(news);//news对象和session2关联
- news.setTitle("EEE");
- tx2.commit();
- session2.close();
4.saveOrUpdate()方法
功能如下:
(1)如果传入的是游离对象就执行update()方法。
(2)如果传入的是临时对象就执行save()方法。
(3)如果传入的是持久化对象,那就直接返回。
saveOrUpdate()方法如何判断对象是临时对象还是游离对象?如果满足下列情况之一,Hibernate就把它作为临时对象,否则就作为游离对象。
(1)OID为null。
(2)映射文件中为<id>设置了unsaved-value属性, 并且Java对象的OID取值与这个unsaved-value 属性值匹配。
5.delete()方法
(1)只要OID和数据表中一条记录对应 ,就计划执行删除操作。
(2)若OID在数据表中没有对应记录,则抛异常。
(3)可以设置Hibernate配置文件 hibernate.use_identifier_rollback为true,使对象删除后,把其OID置为null。
Hibernate基础学习(三)—Session的更多相关文章
- Hibernate基础学习2
Hibernate基础学习2 测试hibernate的一级缓存,事务以及查询语句 1)Hibernate的一些相关概念 hibernate的一级缓存 1)缓存是为了提高该框架对数据库的查询速度 2)一 ...
- Python入门基础学习 三
Python入门基础学习 三 数据类型 Python区分整型和浮点型依靠的是小数点,有小数点就是浮点型. e记法:e就是10的意思,是一种科学的计数法,15000=1.5e4 布尔类型是一种特殊的整形 ...
- Python基础学习三
Python基础学习三 1.列表与元组 len()函数:可以获取列表的元素个数. append()函数:用于在列表的最后添加元素. sort()函数:用于排序元素 insert()函数:用于在指定位置 ...
- Django基础学习三_路由系统
今天主要来学习一下Django的路由系统,视频中只学了一些皮毛,但是也做下总结,主要分为静态路由.动态路由.二级路由 一.先来看下静态路由 1.需要在project中的urls文件中做配置,然后将匹配 ...
- Hibernate学习三----------session详解
© 版权声明:本文为博主原创文章,转载请注明出处 如何获取session对象 1. openSession 2. getCurrentSession - 如果使用getCurrentSession需要 ...
- Hibernate基础学习(五)—对象-关系映射(下)
一.单向n-1 单向n-1关联只需从n的一端可以访问1的一端. 域模型: 从Order到Customer的多对一单向关联.Order类中定义一个Customer属性,而在Customer类不用存放Or ...
- Hibernate基础学习(四)—对象-关系映射(上)
一.映射对象标识符 Java语言按内存地址来识别或区分同一个类的不同对象,而关系数据库按主键值来识别或区分同一个表的不同记录.Hibernate使用对象标识符(OID)来建立内存中的对象和数 ...
- hibernate基础学习
转载自:http://blog.csdn.net/fb281906011/article/details/17628111 一:下载hibernate:http://hibernate.org/orm ...
- Hibernate基础学习(二)—Hibernate相关API介绍
一.Hibernate的核心接口 所有的Hibernate应用中都会访问Hibernate的5个核心接口. (1)Configuration接口: 配置Hibernate,启动Hi ...
随机推荐
- 阿里云服务器 发送邮箱 STMP 25端口 465端口问题 Javamail 25被禁用
我们传统使用的比较简单的是 STMP 25端口收发邮件 今天发现刚购买的阿里云服务器不能作为客户端通过STMP 25端口发送邮件 开始在网上有说发现是JDK1.8的原因,然后自己也把JDK1.8换到了 ...
- JAVA 在程序中存储和修改信息
1.语句和表达式 计算机程序是一组告诉计算机什么的指令,每一个指令称为语句. 2.指定变量类型 变量名.变量存储的信息类型 整型int(-2.14*109~2.14*109).浮点型float(38位 ...
- 业务逻辑 : forex & mlm
业务逻辑 公司通过mlm的制度和顾客进行签约来收取资金,再把资金给第三方公司进行投资,再把所投资的回报给分配给公司和顾客. 公司的资金来自投资者,公司的营销策略来自mlm的制度,由市场人员来创建mlm ...
- spring mvc 结合 Hessian 配置
spring mvc 结合 Hessian 配置 1.先在web.xml中配置 <!-- Hessian配置 --> <servlet> <servlet-name> ...
- ERP顾问工作中应该注意哪些工作是不该做的
1.不要轻易对客户说“不“ 当客户提出一个问题顾问要判断一下,是否属于顾问实施的问题,如果属于顾问实施范畴,而自己又不清楚,这时应把问题纪录下来,和客户解释清楚,回去请教资深顾问给与回答,如果该问题不 ...
- 使用wsimport生成不带JAXBElement对象的代理
如果想使用wsimport生成不带JAXBElement对象的代理,则可以使用jaxws/jaxb绑定文件,如文件命名为binding.txt,内容如 <jaxb:bindings versio ...
- 1029: [JSOI2007]建筑抢修
1029: [JSOI2007]建筑抢修 Time Limit: 4 Sec Memory Limit: 162 MBSubmit: 2382 Solved: 1033[Submit][Statu ...
- Git环境搭建以及上传到GitHub全文记录
1.百度搜索下载git,官网可能很慢,我在百度软件里面下载的.当然可能不是最新版本.一路回车安装就好. 2.设置本机git的用户名和邮箱地址 查看当前电脑是否设置了用户名称 $ git config ...
- 自动化测试工具Appium环境搭建
Appium是一个开源.跨平台的测试框架,可以用来测试原生及混合的移动端应用.Appium支持IOS.Android及FirefoxOS平台.Appium使用WebDriver的json wire协议 ...
- 分享一些自己写的前端库,并骗骗 star(库都是在实际项目中大量运用过的)
最近一两年在一些项目上,通过实际需求出发,编写了一些库在项目中使用,现在将这些项目都稍微整理了一下开源了出来,也许也有刚好能够你也用得上的,顺便也骗一下star.均在项目的README中加了相关的说明 ...