一、持久化对象的状态

       站在持久化的角度, Hibernate 把对象分为 4种状态: 持久化状态,临时状态,游离状态,删除状态.Session 的特定方法能使对象从一个状态转换到另一个状态.  
•临时对象(Transient):
–在使用代理主键的情况下, OID
通常为null
–不处于 Session的缓存中
–在数据库中没有对应的记录
•持久化对象(也叫”托管”)(Persist):
–OID 不为null
–位于 Session缓存中
–若在数据库中已经有和其对应的记录,持久化对象和数据库中的相关记录对应
–Session 在 flush缓存时,会根据持久化对象的属性变化,来同步更新数据库
–在同一个 Session实例的缓存中,数据库表中的每条记录只对应唯一的持久化对象

•删除对象(Removed)

–在数据库中没有和其OID对应的记录

–不再处于Session缓存中

–一般情况下,应用程序不该再使用被删除的对象

•游离对象(也叫”脱管”)(Detached):

–OID不为null

–不再处于Session缓存中

–一般情况需下,游离对象是由持久化对象转变过来的,因此在数据库中可能还存在与它对应的记录

二、Session进行对象持久化的相关方法

1.save() 方法:

•Session 的save()方法使一个临时对象转变为持久化对象
•Session 的save()方法完成以下操作:
–把 News对象加入到Session缓存中,使它进入持久化状态
–选用映射文件指定的标识符生成器,
为持久化对象分配唯一的OID.在使用代理主键的情况下, setId()方法为News对象设置OID使无效的.
–计划执行一条 insert
语句:在 flush缓存的时候
注意:

•Hibernate 通过持久化对象的OID来维持它和数据库相关记录的对应关系.当News对象处于持久化状态时,不允许程序随意修改它的 ID
/**
* 1.使一个临时对象变为持久化对象
* 2.为对象分配id
* 3.在flush()缓存时,会发送一条insert语句
* 4.在save方法之前的id是无效的
* 5.持久化对象的id是不能被修改的
*/
@Test
public void testSave(){
News news=new News();
news.setAuthor("杜甫");
news.setTitle("笑傲江湖");
news.setDate(new Date());
System.out.println(news);
session.save(news);
System.out.println(news);
}

运行结果:可以发现save方法执行前后对象的变化

News [id=null, title=笑傲江湖, author=杜甫, date=Tue Aug 11 20:46:40 CST 2015]
Hibernate:
insert
into
NEWS
(TITLE, AUTHOR, DATE)
values
(?, ?, ?)
News [id=5, title=笑傲江湖, author=杜甫, date=Tue Aug 11 20:46:40 CST 2015]

2、persist()方法

•persist()和
save()区别:

当对一个OID不为Null的对象执行save()方法时,会把该对象以一个新的oid保存到数据库中;  但执行 persist()方法时会抛出一个异常

/**
* 1.persist()方法同样会执行insert操作
* 2.和save()区别:
* 在调用persist()方法之前,若对象已经有id,则不会执行insert,并抛出异常
*/
@Test
public void testPersist(){
News news=new News();
news.setAuthor("王维");
news.setTitle("射雕英雄传");
news.setDate(new Date());
news.setId(200);
System.out.println(news);
session.persist(news);
}

3、get() 方法与load() 方法:

•都可以根据跟定的 OID 从数据库中加载一个持久化对象
•区别:
–当数据库中不存在与 OID 对应的记录时,load() 方法抛出 ObjectNotFoundException异常,而get()方法返回null
–两者采用不同的延迟检索策略:load方法支持延迟加载策略。而get
不支持
/**
* 加载一条对象到内存中
*/
@Test
public void testGet(){
News news=(News) session.get(News.class, 3);
System.out.println(news);
} /**
* get vs load 区别
* 1.执行get()方法会立即加载该对象,若执行load(),如果不立即使用此对象,则不会立即执行查询操作,而返回一个代理对象
* get是立即加载,load是延迟加载
* 2.若数据表中没有对应的记录,get返回null,load若不实用对象,没问题,若需要初始化,抛出异常。
* 3.load方法可能会抛出懒加载异常:在需要初始化代理对象之前已经关闭了session
*
*/
@Test
public void testLoad(){
News news=(News) session.load(News.class, 3);
System.out.println(news);
}

4、update() 方法:

•Session 的 update()方法使一个游离对象转变为持久化对象,并且计划执行一条update语句.
•若希望 Session仅当修改了News对象的属性时,才执行update()语句,可以把映射文件中<class>元素的select-before-update设为true.该属性的默认值为false
•当 update()方法关联一个游离对象时,如果在Session的缓存中已经存在相同
OID的持久化对象,会抛出异常
•当 update()方法关联一个游离对象时,如果在数据库中不存在相应的记录,也会抛出异常. 
/**
* update:
* 1.若更新一个持久化对象,不需要显式调用update()方法,因为在调用commit()方法时,会先执行session的flush
* 2.更新一个游离对象,需要显式的调用update方法,更新之后,并把该游离对象转化为持久化对象
* 3.需要注意的:
* a.无论要更新的游离对象和数据表的记录是否一致,都会发送update语句,
* 如何能让update语句不盲目的发出SQL语句(尤其在对象未改变的情况下)呢?在.hbm.xml文件的class节点设置
* select-before-update=true(此属性默认为false,通常不需要设置)即可
* b.若数据表中没有对应记录,但还调用了update方法,则会抛出异常
* c.用update关联一个游离对象的时候,若session缓存中已经存在一个相同OID的对象,则会抛出异常,因为在session缓存中
* 不能有2个OID相同的对象。
*/
@Test
public void testUpdate(){
News news=(News) session.get(News.class, 3); transcation.commit();
session.close(); session=sessionFactory.openSession();
transcation=session.beginTransaction(); news.setAuthor("金庸");
session.update(news); }
5、saveOrUpdate() 方法
•Session 的 saveOrUpdate()方法同时包含了save()与update()方法的功能,当对象为游离对象时,执行update,对象为临时对象时,执行insert
•判定对象为临时对象的标准
–Java 对象的
OID 为 null
–映射文件中为<id>设置了unsaved-value  属性,并且Java对象的OID取值与这个unsaved-value属性值匹配
/**
* 1、当setId() 方法未注释时,对象存在id,发出update语句,当注释掉的时候,发出insert语句
* 2、若对象的id不为null,并且数据表中没有与之对应的记录,则会抛出异常
*
*/
@Test
public void testSaveOrUpdate(){
News news=new News();
news.setAuthor("王勃");
news.setTitle("凉州词");
news.setDate(new Date());
news.setId(1);
session.saveOrUpdate(news);
}

6、delete() 方法

•Session 的 delete()方法既可以删除一个游离对象,也可以删除一个持久化对象
•Session 的 delete()方法处理过程
–计划执行一条 delete语句
–把对象从 Session缓存中删除,该对象进入删除状态.
•Hibernate 的 cfg.xml配置文件中有一个hibernate.use_identifier_rollback属性,其默认值为false,若把它设为true,将改变delete()方法的运行行为:delete() 方法会把持久化对象或游离对象的 OID设置为null,使它们变为临时对象
/**
* 1.执行删除操作,只要OID与数据表一条记录对应,就会执行delete操作,若没有对应记录,则会抛出异常
*
*/
@Test
public void testDelete(){
News news=new News();
news.setId(2);
session.delete(news);
}

7、evict() 方法:从缓存中移除指定的持久化对象

8、Hibernate调用存储过程:
•Session 的 doWork(Work)方法用于执行Work对象指定的操作,即调用Work对象的execute()方法.Session 会把当前使用的数据库连接传递给 execute()方法.
@Test
public void testDoWork(){
session.doWork(new Work() { @Override
public void execute(Connection connection) throws SQLException {
// 调用存储过程
String procedure="{call testProcedure()}";
CallableStatement cs=connection.prepareCall(procedure);
cs.executeUpdate(); }
});
}

9、Hibernate与触发器协同工作:

•Hibernate与数据库中的触发器协同工作时,会造成两类问题
–触发器使 Session的缓存中的持久化对象与数据库中对应的数据不一致:触发器运行在数据库中,它执行的操作对Session是透明的
–Session 的 update()方法盲目地激发触发器:无论游离对象的属性是否发生变化,都会执行update语句,而update语句会激发数据库中相应的触发器
•解决方案:
–在执行完 Session的相关操作后,立即调用Session的flush()和refresh()方法,迫使Session的缓存与数据库同步(refresh()方法重新从数据库中加载对象)
–在映射文件的的 <class>元素中设置select-before-update属性:当Session的update或saveOrUpdate()方法更新一个游离对象时,会先执行Select语句,获得当前游离对象在数据库中的最新数据,只有在不一致的情况下才会执行update语句






Hibernate之Session对象的相关方法以及持久化对象的状态的更多相关文章

  1. Hibernate,Session方法使得java对象进入持久化状态;持久化对象特征

    以下情况java对象进入持久化状态: session.save()方法把临时对象转变为持久化对象. session.load()和session.get()方法得到的对象总是处于持久化状态. sess ...

  2. (转) Hibernate框架基础——操纵持久化对象的方法(Session中)

    http://blog.csdn.net/yerenyuan_pku/article/details/52761021 上一篇文章中我们学习了Hibernate中java对象的状态以及对象的状态之间如 ...

  3. Hibernate持久化对象状态

    在Hibernate中,持久化对象再被操作过程中分为三个时期.这三个时期和session周期相关. 各自是瞬时(Transient),持久太(persistent)和游离态(Detached) 瞬时状 ...

  4. hibernate系列笔记(3)---持久化对象

    持久化对象 再讲持久化对象之前,我们先来理解有关session中get方法与 load方法区别: 简单总结: (1)如果你使用load方法,hibernate认为该id对应的对象(数据库记录)在数据库 ...

  5. 1.1Hibernate持久化类和Hibernate持久化对象状态

    一.持久化对象po类 1.po定义 PO,是Persistent Object的缩写,是持久化类.PO是由PO=POJO+hbm映射配置组成. 2.通俗理解 PO类即持久化类,其实就是一个普通的Jav ...

  6. hibernate学习之持久化对象

    Hibernate对其持久化对象实现了缓存管理,来提高系统性能,Hibernate支持两级缓存管理,一级缓存 是由Session提供的,因此它只存在于Session的生命周期中,是Session所内置 ...

  7. hibernate框架(3)---持久化对象

    持久化对象 再讲持久化对象之前,我们先来理解有关session中get方法与 load方法区别: 简单总结: (1)如果你使用load方法,hibernate认为该id对应的对象(数据库记录)在数据库 ...

  8. Hibernate中持久化类与持久化对象

    1.JavaBean类 JavaBean类是实体类,必须一下属性,private修饰的成员属性,public修饰的getter与setter访问方法,public修饰的空参构造器,实现Serializ ...

  9. Hibernate -- 操作持久化对象

    知识点2: session概述 Session 接口是 Hibernate 向应用程序提供的操纵对数据库的最主要的接口,它提供了基本的保存,更新, 删除和加载Java对象的方法. 知识点3:理解ses ...

随机推荐

  1. 一种扩大View点击范围的方法

    Rect rect = new Rect();mBt0.getHitRect(rect); rect.bottom += 400; TouchDelegate touchDelegate = new ...

  2. js实现继承的五种方式

    function Parent(firstname) { this.fname=firstname; ; this.sayAge=function() { console.log(this.age); ...

  3. git drupal eclipse

    eclispe如何打补丁https://www.drupal.org/patch/apply打patch,初级详细教程https://www.drupal.org/node/620014

  4. Java微框架:不可忽视的新趋势--转载

    原文:http://www.infoq.com/cn/news/2015/06/Java-Spark-Jodd-Ninja?utm_campaign=infoq_content&utm_sou ...

  5. swift之元组类型

    一.元组类型是有N个任意类型的数据组成(N>=0),组成元组类型的数据可以称为“元素” 二.元组的定义 如:let position = (x:10.5,y:20)    //两个元素的元组 l ...

  6. 将cocos2dx+lua创建的游戏port到windows phone

    在整个Port的过程中遇到的问题总结例如以下 1.一定要使用最新版本号的cocos2dx,原因大家看一下changelog就知道了,近期的cocos2dx版本号都是在修windows phone上的b ...

  7. 实验与作业(Python)-文件操作

    1.CSV文件的处理 下载-身份证号文件 导入: 读入"身份证号.txt",然后打印出来.注意:是否多打了一行,为什么? 读入"身份证号.txt",然后存储到& ...

  8. 简单QR分解之Gram-Schmit正交化&amp;&amp;Householder变换&amp;&amp;Givens Rotation变换&amp;&amp;计算步骤

  9. Java技术开发中的坑

    1.(2014/05/28)struts2中使用eclipse自动获取getter和setter方法的坑 今天着实被eclipse坑了一把,平时遇到get和set方法时,我都是通过eclipse自动生 ...

  10. label语句、break语句和continue语句

    label语句 可以在代码中添加标签,以便使用.以下是label语句的语法: label:statement 示例: start: for (var i = 0; i < count; i++) ...