hibernate中session的三种状态

Hibernate中的对象有三种状态:临时状态 (Transient),持久状态 (Persistent),游离状态(Detached)

1. session三种状态:

1. 1.临时状态(Transient)

由 new 命令开辟内存空间的 Java 对象,也就是平时所熟悉的普通 Java 对象,该对象不曾进行持久化,未与任何Session相关联,也叫自由态,只存在于内存中,而在数据库中没有相应数据。用new创建的对象,它没有持久化,没有处于Session中,处于此状态的对象叫临时对象;

如: Student stu = new Student();

临时对象特点:

(1) 不和 Session 实例关联

(2) 在数据库中没有和临时对象关联的记录

2. 2. 持久状态 (Persistent)

持久的实例在数据库中有对应的记录,并拥有一个持久化标识 (identifier).该对象与session关联并且在数据库中有相应数据。已经持久化,加入到了Session缓存中。如通过hibernate语句保存的对象。处于此状态的对象叫持久对象;

持久对象总是与 Session 和 Transaction 相关联,在一个 Session 中,对持久对象的改变不会马上对数据库进行变更,而必须在Transaction 终止,也就是执行 commit() 之后,才在数据库中真正运行 SQL 进行变更,持久对象的状态才会与数据库进行同步。在同步之前的持久对象称为脏 (dirty) 对象。

临时对象转为持久对象:

(1) 通过 Session 的 save() 和 saveOrUpdate() 方法把一个临时对象与数据库相关联,这个临时对象就成为持久化对象。

(2) 使用 fine(),get(),load() 和 iterater() 待方法查询到的数据对象,将成为持久化对象。

持久化对象的特点:

(1) 和 Session 实例关联

(2) 在数据库中有和持久对象关联的记录

3. 3. 游离状态 (Detached)

与持久对象关联的 Session 被关闭后,对象就变为游离对象。对游离对象的引用依然有效,对象可继续被修改。

持久化对象脱离了Session的对象。如Session缓存被清空的对象。该对象已经持久化,但不在Session缓存中。处于此状态的对象叫游离对象;;

游离对象特点:

(1) 本质上和临时对象相同

(2) 只是临时对象多了一个数据库记录标识值 id.

持久对象转为游离对象:

当执行 close() 或 clear(),evict() 之后,持久对象会变为游离对象。

游离对象转为持久对象:

通过 Session 的 update(),saveOrUpdate() 和 lock() 等方法,把游离对象变为持久对象。

游离对象和临时对象异同:

两者都不会被Session关联,对象属性和数据库可能不一致;

游离对象有持久化对象关闭Session而转化而来,在内存中还有对象所以此时就变成游离状态了;

Hibernate和SQL的关系:

在操作了hibernate的方法如save()等后,并没有直接生成sql语句,去操作数据库,而是把这些更新存入Session中,只有Session缓存要被更新时,底层的sql语句才能执行,数据存入数据库;

三种状态相互转化的状态图如下:

Hibernate三种状态

4 .结合 save(),update(),saveOrUpdate() 方法说明对象的状态

(1)Save() 方法将临时对象保存到数据库,对象的临时状态将变为持久化状态。当对象在持久化状态时,它一直位于 Session 的缓存中,对它的任何操作在事务提交时都将同步到数据库,因此,对一个已经持久的对象调用 save() 或 update() 方法是没有意义的。如:

Student stu = new Strudnet();

stu.setCarId(“200234567”);

stu.setId(“100”);

Session session = HibernateUtil.getSessionFactory().getCurrentSession();// 打开 Session

session.beginTransaction();// 开启事务

session.save(stu);

stu.setCardId(“20076548”);

session.save(stu); // 无效

session.update(stu); // 无效

session.getTransaction().commit();// 提交事务,

session.close();关闭 Session

(2)update() 方法两种用途重新关联游离对象为持久化状态对象,显示调用 update() 以更新对象。调用 update() 只为了关联一个游离对象到持久状态,当对象已经是持久状态时,调用 update() 就没有多大意义了。如:

Session session = HibernateUtil.getSessionFactory().getCurrentSession();// 打开 Session

session.beginTransaction();// 开启事务

stu = (Student)session.get(Student.class,”123456”);

stu.setName(“Body”);

session.update(stu); // 由于 stu 是持久对象,必然位于 Session 缓冲中,对 stu 所做的变更将 // 被同步到数据库中。所以 update() 是没有意义的,可以不要这句效果一样的。

session.getTransaction().commit();// 提交事务,

session.close();关闭 Session

Hibernate 总是执行 update 语句,不管这个游离对象在离开 Session 之后有没有更改过,在清理缓存时 Hibernate 总是发送一条update 语句,以确保游离对象和数据库记录的数据一致。

如:

Student stu = new Strudnet();

stu.setCarId(“1234”);

Session session1 = HibernateUtil.getSessionFactory().getCurrentSession();// 打开 Session

session1.beginTransaction();// 开启事务

session1.save(stu);

session1.getTransaction().commit();// 提交事务,

session1.close();关闭 Session

stu.set(“4567”); // 对游离对象进行更改

Session session2 = HibernateUtil.getSessionFactory().getCurrentSession();// 打开 Session

session2.beginTransaction();// 开启事务

session2.update(stu);

session2.getTransaction().commit();// 提交事务,

session2.close();关闭 Session

注:即使把 session2.update(stu); 这句去掉,提交事务时仍然会执行一条 update() 语句。

如果希望只有脱管对象改变了, Hibernate 才生成 update 语句,可以把映射文件中 <class> 标签的 select-before-update 设为true, 这种会先发送一条 select 语句取得数据库中的值,判断值是否相同,如果相同就不执行 update 语句。不过这种做法有一定的缺点,每次 update 语句之前总是要发送一条多余的 select 语句,影响性能。对于偶尔更改的类,设置才是有效的,对于经常要更改的类这样做是影响效率的。

(3)saveOrUpdate() 方法兼具 save() 和 update() 方法的功能,对于传入的对象, saveOrUpdate() 首先判断其是脱管对象还是临时对象,然后调用合适的方法。

注:并非到事务提交才对数据库操作,提交只是把变更持久化,实际上通过flush是可以操作的,只是这个变更只能在本事务看到而已。

一,Session.save(user)运行机理。

1,把User对象加入缓存中,使它变成持久化对象;

2,选用映射文件指定的标识生成ID;

3,在Session清理缓存时候执行:在底层生成一个insert sql语句,把对象存入数据库;

注意:在你执行Session.save(user)后,在Session清理缓存前,如果你修改user对象属性值,那么最终存入数据库的值将是最后修改的值;此过程中ID不能被修改;

二,Session.delete(user)运行过程。

如果user是持久化对象,则执行删除操作,同样底层数据库的执行条件是:在Session清理缓存时候;

如果user是游离对象:

1,将user对象和Session关联,使之成为持久化对象;

2,然后按照user 是持久化对象的过程执行;

三态之间的转换方法:

①如何成为自由态?

    对象通过构造方法成为自由态;持久态和游离态则通过session的delete方法成为自由态

②如何成为持久态?

    对象可以由session的load或get方法直接成为持久态;自由态对象可以通过save,saveOrUpdate或persist方法成为持久态;游离态对象则可以通过update,saveOrUpdate成为持久态

③如何成为游离态?

    游离态只能由持久态转换而来,通过close或clear方法实现。

临时态转换到持久态     save()    saveOrUpdate()

持久态转换到临时态     delete()

持久态转换到游离态     evict()    close()  clear()

游离态转换到持久态     update()   saveOrUpdate()    lock()


几种转换方法的对比:

1.get 与load

都是从数据库中加载数据封装为java对象,使得java对象从自由态直接变为持久态;

但是有两点区别:①get返回对象可以为null,load返回值则始终不为null,找不到时会抛异常②get即时执行insert,而load则是在使用此对象时才执行insert

2.save,update与saveOrUpdate

save是将自由态转为持久态,而update是将游离态转为持久态,saveOrUpdate可以说是两者的综合,它执行时先判断对象的状态(主要是通过有无主键判断的),若是自由态,则save,若是游离态,则update

3.save与persist

两者都是将对象由自由态转为持久态,但返回值不同:save返回主键值,而persist不返回

4,saveOrUpdate与merge

两者都是将自由态或游离态对象与数据库关联,但merge不改变对象的原有状态

此外,对clear与flush方法也作介绍。clear是将session中的对象全部变为游离态,是对象由持久态变为游离态的一种方法(另外一种是关闭session);flush方法时为了使update操作能即时进行(正常情况下,只有在事务关闭时才进行update操作)。

Hibernate获得Session的两个方法 

大家都知道,使用Hibernate对数据进行操作最重要的是获得一个Session。 

首先获得一个SessionFactory,通过.config().buildSessionFactory(),获得一个SessionFactory 进而取得Session的方法在Hibernate里有两种: 

1:Session session = sessionFactory.openSession(); 

    该种方法是创建一个新的session,不论当前的环境中是否已经创建,都会创建; 

    且当session提交成功后,需要手动关闭这个session; 

2:Session session = sessionFactory.getCurrentSession(); 

    该方法是获取当前环境中的session,若环境中已经存在session,则取出当前的;若无session则创建一个新的, 

    只要当前的session提交后,该session会自动关闭,其后再使用getCurrentSession()方法,则是创建一个新的session; 

    使用以上两种方式还需要注意的是事务控制,如果使用第一种方法,openSession()也许会导致数据的不一致, 

    

    例如在用户管理功能模块中,我们对用户的各种操作都需要做日志记录,此时要两张数据表同时提交成功,否则都不进行数据的写入;所以我们要使用第二种方式来取得session。 

特别强调:这两种取得Session的方法不能混用。原因很简单,在Hibernate中,Session是一个接口。两个获取session的方法并非是同一个实现,故不可混用!


转载于:https://my.oschina.net/u/2331760/blog/617916

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值