一、概述

     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的更多相关文章

  1. Hibernate基础学习2

    Hibernate基础学习2 测试hibernate的一级缓存,事务以及查询语句 1)Hibernate的一些相关概念 hibernate的一级缓存 1)缓存是为了提高该框架对数据库的查询速度 2)一 ...

  2. Python入门基础学习 三

    Python入门基础学习 三 数据类型 Python区分整型和浮点型依靠的是小数点,有小数点就是浮点型. e记法:e就是10的意思,是一种科学的计数法,15000=1.5e4 布尔类型是一种特殊的整形 ...

  3. Python基础学习三

    Python基础学习三 1.列表与元组 len()函数:可以获取列表的元素个数. append()函数:用于在列表的最后添加元素. sort()函数:用于排序元素 insert()函数:用于在指定位置 ...

  4. Django基础学习三_路由系统

    今天主要来学习一下Django的路由系统,视频中只学了一些皮毛,但是也做下总结,主要分为静态路由.动态路由.二级路由 一.先来看下静态路由 1.需要在project中的urls文件中做配置,然后将匹配 ...

  5. Hibernate学习三----------session详解

    © 版权声明:本文为博主原创文章,转载请注明出处 如何获取session对象 1. openSession 2. getCurrentSession - 如果使用getCurrentSession需要 ...

  6. Hibernate基础学习(五)—对象-关系映射(下)

    一.单向n-1 单向n-1关联只需从n的一端可以访问1的一端. 域模型: 从Order到Customer的多对一单向关联.Order类中定义一个Customer属性,而在Customer类不用存放Or ...

  7. Hibernate基础学习(四)—对象-关系映射(上)

    一.映射对象标识符      Java语言按内存地址来识别或区分同一个类的不同对象,而关系数据库按主键值来识别或区分同一个表的不同记录.Hibernate使用对象标识符(OID)来建立内存中的对象和数 ...

  8. hibernate基础学习

    转载自:http://blog.csdn.net/fb281906011/article/details/17628111 一:下载hibernate:http://hibernate.org/orm ...

  9. Hibernate基础学习(二)—Hibernate相关API介绍

    一.Hibernate的核心接口      所有的Hibernate应用中都会访问Hibernate的5个核心接口.      (1)Configuration接口: 配置Hibernate,启动Hi ...

随机推荐

  1. php 手动搭建环境

    php手动搭建环境有好多种组合,版本号不一致,会导致搭建失败. 我搭建的组合是: php5.6+MySQL5.6+Apache2.4的组合. 一.PHP语言包下载 首先从官网上下载php5.6 htt ...

  2. Cocos2d-x shader学习2: 模糊(Blur)

    模糊效果在游戏中经常会用到,有的为了突出前景会把背景给模糊化,有的是因为一些技能需要模糊效果.模糊是shader中较为简单的一种应用.cocos2dx 3.x给的demo中,就有sprite的模糊的效 ...

  3. KoaHub平台基于Node.js开发的Koa的模板系统handlebars插件代码详情

    koahub-handlebars koahub-handlebars koahub handlebars templates Installation $ npm install koahub-ha ...

  4. 3408: [Usaco2009 Oct]Heat Wave 热浪

    3408: [Usaco2009 Oct]Heat Wave 热浪 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 67  Solved: 55[Subm ...

  5. Oracle物化视图,物化视图日志,增量刷新同步远程数据库

    1.创建DBLINK -- Drop existing database link drop public database link LQPVPUB; -- Create database link ...

  6. Ubuntu 不支持 rpm

    不是第一次犯这个错误了. 记一下. 每次安装jdk 的时候,习惯性下载rpm包. 然后的,然后在 ubuntu上rpm 安装的时候就跪了.. ubuntu需要使用Alien 把rpm 转成 deb再安 ...

  7. jsp想js,action传值

    1.struts2 action如何向JSP的JS函数传值 action中定义变量 public class TestAction extends ActionSupport implements S ...

  8. linux 私房菜 CH6 Linux 的档案权限与目录配置

    查看文件属性 ls -al 第一栏:类型与权限 d:目录: -:档案: l:链接档: b:可随机存取装置: c:一次性存取装置: 第二栏:有多少档名连结到此节点 第三栏:拥有者 第四栏:所属群组 第五 ...

  9. HBase架构

    文章作者:luxianghao 文章来源:http://www.cnblogs.com/luxianghao/p/6573817.html  转载请注明,谢谢合作. 免责声明:文章内容仅代表个人观点, ...

  10. Python中类的方法属性与方法属性的动态绑定

    最近在学习python,纯粹是自己的兴趣爱好,然而并没有系统地看python编程书籍,觉得上面描述过于繁琐,在网站找了一些学习的网站,发现廖雪峰老师的网站上面的学习资源很不错,而且言简意赅,提取了一些 ...