`

hibernate中session的三种状态

阅读更多

Hibernate中的对象有三种状态: 瞬时状态 (Transient),持久状态 (Persistent),

1. 脱管状态 (Detached)

1. 1. 瞬时状态 (Transient)

new 命令开辟内存空间的 Java 对象,也就是平时所熟悉的普通 Java 对象。

如: Student stu = new Student();

瞬时对象特点:

(1) 不和 Session 实例关联

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

2. 2. 持久状态 (Persistent)

持久的实例在数据库中有对应的记录,并拥有一个持久化标识 (identifier).

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

瞬时对象转为持久对象:

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

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

持久化对象的特点:

(1) Session 实例关联

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

3. 3. 脱管状态 (Detached)

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

脱管对象特点:

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

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

持久对象转为脱管对象:

当执行 close() clear(),evict() 之后,持久对象会变为脱管对象。

瞬时对象转为持久对象:

通过 Session update(),saveOrUpdate() lock() 等方法,把脱管对象变为持久对象。

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

Hibernate三种状态

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

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

Student stu = new Strudnet();

stu.setCarId(“200234567”);

stu.setId(“100”);

// 打开 Session, 开启事务

session.save(stu);

stu.setCardId(“20076548”);

session.save(stu); // 无效

session.update(stu); // 无效

// 提交事务,关闭 Session

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

// 打开 session ,开启事务 

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

stu.setName(“Body”);

session.update(stu); // 由于 stu 是持久对象,必然位于 Session 缓冲中,

stu 所做的变更将 // 被同步到数据库中。所以 update() 是没有意义的,可以不要这句效果一样的。

// 提交事务,关闭 Session

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

Student stu = new Strudnet();

stu.setCarId(“1234”);

// 打开 Session1, 开启事务

session1.save(stu);

// 提交事务,关闭 Session1

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

// 打开 Session2, 开启事务

session2.update(stu);

// 提交事务,关闭 Session2

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

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

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

分享到:
评论
37 楼 chenyu1520 2012-03-15  
Student stu = new Strudnet();

stu.setCarId(“200234567”);

stu.setId(“100”);

// 打开 Session, 开启事务

session.save(stu);

stu.setCardId(“20076548”);

session.save(stu); // 无效    ***这句错了,我试了,有效,而且你写的有问题**

session.update(stu); // 无效

// 提交事务,关闭 Session
36 楼 cczakai 2011-04-14  
当session1.save(stu); 的时候已经置入了Session缓存中了,而你第二次操作的时候,直接可以改变对象即可,因为对象状态为持久态,假使事物提交才会从持久态变成游离态了。



35 楼 ancle*f 2011-04-13  
cesymm 写道
总体来说,是初级贴.
纠证一点问题

Student stu = new Strudnet();

stu.setCarId(“1234”);

// 打开 Session1, 开启事务

session1.save(stu);

// 提交事务,关闭 Session1

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

// 打开 Session2, 开启事务

session2.update(stu);

// 提交事务,关闭 Session2

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


去掉为什么会执行?
如果去掉,它又不在Session2的缓存中,如何来执行update语句呢。

34 楼 lin23871 2011-04-13  
sdfasdfd
33 楼 jayfans3 2011-04-13  
caoyangx 写道
你的标题少了一个b。

真JB强人。
32 楼 optimism_best 2011-04-03  
理解得很详细,在具体的开发中,才会让自己有更深刻的认识
31 楼 ttl200909 2011-04-03  
写的真清楚,学习了!!
30 楼 肉嘎嘎 2011-04-03  
LZ写得不错!

另外:
laoshifu 写道
我想问一下:hibernate的三种状态,是为了理解而提出来的概念还是,hibernate提供了对象的状态的实现?


hibernate提供这三种状态,个人认为是便于理解,便于在开发的时候清楚的知道实体类的状态和数据在事务中的变化,这点对其实是个基础点,因为EJB也有这类似的状态的!
29 楼 ericslegend 2011-03-29  
skcmm 写道
cczakai 写道
cesymm 写道
总体来说,是初级贴.
纠证一点问题

Student stu = new Strudnet();

stu.setCarId(“1234”);

// 打开 Session1, 开启事务

session1.save(stu);

// 提交事务,关闭 Session1

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

// 打开 Session2, 开启事务

session2.update(stu);

// 提交事务,关闭 Session2

注:即使把 session2.update(stu); 这句去掉,提交事务时仍然会执行一条 update() 语句。
你把session2.update(stu);去掉不会执行update语句,只会执行第一个session.save()生成的insert 语句




我不太赞同

session的save()或者update()的操作就提交事务了,

事务操作不是session这类控制的,而session中的save()或者update()不过跟数据库进行insert,update是一样,没有commit,怎么就提交事务了呢

我们的理解就是对象进入了持久化状态,但如果你没有提交数据,别人查询的时候还是你操作之前的数据,如果有另一个事务同时访问同一数据,则出现锁表或者有能出现幻觉(脏数据)。


既然已经提交事务,session关闭的话,数据已经更新到数据库内,session2.update 如果注释的话 绝对会不起作用  赞同楼上的

会起作用
28 楼 dominic6988 2011-03-29  
21jhf 写道
21jhf 写道
请教个问题,对象是持久化状态,如果先delete(),然后执行update(), 对象是什么状态?用两个不同的session呢?是不是会报错啊?

public void testGet(){
Session session = null;
Transaction tx = null;
try{
session = SessionFactoryUtils.getSession();
tx = session.beginTransaction();

/*User user = new User();
user.setName("张三");
user.setPassword("123456");
user.setCreateTime(new Date());
user.setExpireTime(new Date());
*/
User user = (User)session.get(User.class,"402880e42ef34964012ef34966530000");
session.delete(user);
log.debug("++++++++++++++userName:"+user.getName());
user.setName("李四");
session.update(user);
tx.commit();

}catch(Exception e){
e.printStackTrace();
tx.rollback();
}finally{
SessionFactoryUtils.closeSession(session);
}
}


测试过了,出现了异常
20:56:22,593 DEBUG Loader:2050 - done entity load
20:56:22,609 DEBUG HibernateTest:59 - ++++++++++++++userName:张三
org.hibernate.ObjectDeletedException: deleted instance passed to update(): [<null entity name>#<null>]
at org.hibernate.event.def.DefaultUpdateEventListener.performSaveOrUpdate(DefaultUpdateEventListener.java:50)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:93)
at org.hibernate.impl.SessionImpl.fireUpdate(SessionImpl.java:742)
at org.hibernate.impl.SessionImpl.update(SessionImpl.java:730)
at org.hibernate.impl.SessionImpl.update(SessionImpl.java:722)
at com.navagate.client.HibernateTest.testGet(HibernateTest.java:61)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at junit.framework.TestCase.runTest(TestCase.java:168)
at junit.framework.TestCase.runBare(TestCase.java:134)
at org.hibernate.testing.junit.UnitTestCase.runBare(UnitTestCase.java:63)
at junit.framework.TestResult$1.protect(TestResult.java:110)
at junit.framework.TestResult.runProtected(TestResult.java:128)
at junit.framework.TestResult.run(TestResult.java:113)
at junit.framework.TestCase.run(TestCase.java:124)
at junit.framework.TestSuite.runTest(TestSuite.java:243)
at junit.framework.TestSuite.run(TestSuite.java:238)
at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:83)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
20:56:22,609 DEBUG JDBCTransaction:182 - rollback
20:56:22,625 DEBUG JDBCTransaction:193 - rolled back JDBC Connection
20:56:22,625 DEBUG ConnectionManager:427 - aggressively releasing JDBC connection



执行过delete说明这条记录已经删除了,你怎么还能做更新操作呢.
27 楼 21jhf 2011-03-28  
21jhf 写道
请教个问题,对象是持久化状态,如果先delete(),然后执行update(), 对象是什么状态?用两个不同的session呢?是不是会报错啊?

public void testGet(){
Session session = null;
Transaction tx = null;
try{
session = SessionFactoryUtils.getSession();
tx = session.beginTransaction();

/*User user = new User();
user.setName("张三");
user.setPassword("123456");
user.setCreateTime(new Date());
user.setExpireTime(new Date());
*/
User user = (User)session.get(User.class,"402880e42ef34964012ef34966530000");
session.delete(user);
log.debug("++++++++++++++userName:"+user.getName());
user.setName("李四");
session.update(user);
tx.commit();

}catch(Exception e){
e.printStackTrace();
tx.rollback();
}finally{
SessionFactoryUtils.closeSession(session);
}
}


测试过了,出现了异常
20:56:22,593 DEBUG Loader:2050 - done entity load
20:56:22,609 DEBUG HibernateTest:59 - ++++++++++++++userName:张三
org.hibernate.ObjectDeletedException: deleted instance passed to update(): [<null entity name>#<null>]
at org.hibernate.event.def.DefaultUpdateEventListener.performSaveOrUpdate(DefaultUpdateEventListener.java:50)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:93)
at org.hibernate.impl.SessionImpl.fireUpdate(SessionImpl.java:742)
at org.hibernate.impl.SessionImpl.update(SessionImpl.java:730)
at org.hibernate.impl.SessionImpl.update(SessionImpl.java:722)
at com.navagate.client.HibernateTest.testGet(HibernateTest.java:61)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at junit.framework.TestCase.runTest(TestCase.java:168)
at junit.framework.TestCase.runBare(TestCase.java:134)
at org.hibernate.testing.junit.UnitTestCase.runBare(UnitTestCase.java:63)
at junit.framework.TestResult$1.protect(TestResult.java:110)
at junit.framework.TestResult.runProtected(TestResult.java:128)
at junit.framework.TestResult.run(TestResult.java:113)
at junit.framework.TestCase.run(TestCase.java:124)
at junit.framework.TestSuite.runTest(TestSuite.java:243)
at junit.framework.TestSuite.run(TestSuite.java:238)
at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:83)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
20:56:22,609 DEBUG JDBCTransaction:182 - rollback
20:56:22,625 DEBUG JDBCTransaction:193 - rolled back JDBC Connection
20:56:22,625 DEBUG ConnectionManager:427 - aggressively releasing JDBC connection
26 楼 21jhf 2011-03-28  
请教个问题,对象是持久化状态,如果先delete(),然后执行update(), 对象是什么状态?用两个不同的session呢?是不是会报错啊?
25 楼 nophaern 2011-03-28  
p_x1984 写道
已经该正过来了。

test-text
24 楼 p_x1984 2011-03-22  
已经该正过来了。
23 楼 href 2011-03-21  
caoyangx 写道
你的标题少了一个b。

观察的相当仔细,漏掉的b,在看看你头像,果然很搭
22 楼 skcmm 2011-03-19  
cczakai 写道
cesymm 写道
总体来说,是初级贴.
纠证一点问题

Student stu = new Strudnet();

stu.setCarId(“1234”);

// 打开 Session1, 开启事务

session1.save(stu);

// 提交事务,关闭 Session1

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

// 打开 Session2, 开启事务

session2.update(stu);

// 提交事务,关闭 Session2

注:即使把 session2.update(stu); 这句去掉,提交事务时仍然会执行一条 update() 语句。
你把session2.update(stu);去掉不会执行update语句,只会执行第一个session.save()生成的insert 语句




我不太赞同

session的save()或者update()的操作就提交事务了,

事务操作不是session这类控制的,而session中的save()或者update()不过跟数据库进行insert,update是一样,没有commit,怎么就提交事务了呢

我们的理解就是对象进入了持久化状态,但如果你没有提交数据,别人查询的时候还是你操作之前的数据,如果有另一个事务同时访问同一数据,则出现锁表或者有能出现幻觉(脏数据)。


既然已经提交事务,session关闭的话,数据已经更新到数据库内,session2.update 如果注释的话 绝对会不起作用  赞同楼上的
21 楼 cczakai 2011-03-18  
cesymm 写道
总体来说,是初级贴.
纠证一点问题

Student stu = new Strudnet();

stu.setCarId(“1234”);

// 打开 Session1, 开启事务

session1.save(stu);

// 提交事务,关闭 Session1

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

// 打开 Session2, 开启事务

session2.update(stu);

// 提交事务,关闭 Session2

注:即使把 session2.update(stu); 这句去掉,提交事务时仍然会执行一条 update() 语句。
你把session2.update(stu);去掉不会执行update语句,只会执行第一个session.save()生成的insert 语句




我不太赞同

session的save()或者update()的操作就提交事务了,

事务操作不是session这类控制的,而session中的save()或者update()不过跟数据库进行insert,update是一样,没有commit,怎么就提交事务了呢

我们的理解就是对象进入了持久化状态,但如果你没有提交数据,别人查询的时候还是你操作之前的数据,如果有另一个事务同时访问同一数据,则出现锁表或者有能出现幻觉(脏数据)。
20 楼 earring 2011-03-18  
  总结的不错,赞一个~
19 楼 cesymm 2011-03-18  
总体来说,是初级贴.
纠证一点问题

Student stu = new Strudnet();

stu.setCarId(“1234”);

// 打开 Session1, 开启事务

session1.save(stu);

// 提交事务,关闭 Session1

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

// 打开 Session2, 开启事务

session2.update(stu);

// 提交事务,关闭 Session2

注:即使把 session2.update(stu); 这句去掉,提交事务时仍然会执行一条 update() 语句。
你把session2.update(stu);去掉不会执行update语句,只会执行第一个session.save()生成的insert 语句

18 楼 cczakai 2011-03-18  
当确定对象与数据库表对象关联关系时候,实际上我们对对象的操作,已经成为对表的操作了。

其实这种思想,体现了对象与数据库表对象的关联关系。

往往做设计对物理实体的操作都可以用OO思想来理解。

比如数据库表实体可以被做作为虚拟对象处理,当虚拟对象被处理了,

相应触发了底层实体层变化,而这部分属于高内聚,设计时候类的功能特性必须具

备实体的作用效果。


通过了三种状态,主要还是为了解决对象与数据库表对象的映射,体现了hibernate的面向对象的特性。

相关推荐

    hibernate中session对象的状态详解

    hibernate中session对象的状态详解

    hibernate对象三种状态

    在Java的持久化框架Hibernate中,对象存在三种不同的状态,分别是持久态(Persistent)、自由态(Transient)和游离态(Detached)。这三种状态分别对应了对象与数据库的关联程度,理解它们对于高效地使用Hibernate...

    Hibernate中对象的三种状态

    在Java的持久化框架Hibernate中,对象的状态管理是其核心特性之一...总之,理解Hibernate中对象的三种状态以及它们之间的转换对于开发人员来说至关重要。熟练掌握这些概念有助于编写出更加高效、可靠的Java持久化代码。

    Hibernate 对象的三种状态和特点

    以下是Hibernate对象的三种主要状态及其特点: 1) 临时状态(Transient State): 当通过`new`关键字创建一个新的对象时,该对象处于临时状态。在这个状态下,对象并未与任何Session关联,因此它的变化不会自动反映...

    Hibernate Session 4种对象状态.docx

    Hibernate将对象的状态划分为四种:临时状态、持久化状态、游离状态和删除状态。这些状态反映了对象与数据库记录之间的关系,有助于理解Hibernate如何管理和操作数据。 1. **临时状态(Transient State)**: 当一...

    Hibernate_Session_Transaction

    在Java的持久化框架Hibernate中,`Session`和`Transaction`是两个至关重要的概念,它们在数据管理和事务处理中起到核心作用。这篇文章将深入解析这两个概念及其相关知识点。 `Session`是Hibernate提供的一种与...

    Hibernate(session管理)

    本文将深入探讨Hibernate中的核心概念——Session管理。 首先,理解Session在Hibernate中的角色至关重要。Session是Hibernate的主要工作单元,它是应用程序与数据库之间的桥梁。它负责保存、检索和更新Java对象,...

    hibernate和session学习

    在Hibernate中,`SessionFactory`是核心组件之一,它是线程安全的,用于创建`Session`对象。`SessionFactory`通常在应用启动时创建一次,然后在整个应用生命周期中复用。创建`SessionFactory`需要通过读取Hibernate...

    Hibernate的Session的javadoc

    Hibernate的Session接口是Java应用程序与Hibernate之间主要的运行时交互接口,它提供了对持久化对象的创建、读取和删除操作。Session的概念是基于对象的状态管理和数据库事务的,它的生命周期通常与一个物理事务绑定...

    Hibernate三种状态

    Hibernate对象有三种状态:瞬时状态(Transient)、持久状态(Persistent)和脱管状态(Detached)。理解这些状态对于优化数据操作和避免潜在的问题至关重要。 首先,瞬时状态(Transient)是指通过new关键字创建的...

    hibernate session生命周期示例

    在Hibernate中,事务和Session是紧密关联的,事务的边界通常定义了Session的工作范围。 3. **持久化操作**: - **加载和检索**:使用`get()`或`load()`方法可以加载一个实体,如果对象存在于数据库,Hibernate将...

    hibernate的session.flush

    `Session.flush()`方法是一个关键的操作,它强制Hibernate将内存中的对象状态同步到数据库,确保数据的一致性。这篇博客深入探讨了`Session.flush()`的工作原理和应用场景。 `Session`在Hibernate中主要有以下职责...

    Hibernate三种状态区分

    在 Hibernate 中,对象有三种不同的状态,这些状态决定了对象与数据库之间的关联程度以及如何进行数据操作。理解这些状态对于有效地使用 Hibernate 至关重要。 1. **瞬时态(Transient)**: - 瞬时态的对象是刚刚...

    Hibernate Session释放模式

    在Java的持久化框架Hibernate中,Session对象是与数据库交互的核心组件,它负责管理对象的持久状态。在处理大量数据或者长时间运行的事务时,合理地管理Session的生命周期至关重要,这就涉及到了Hibernate的Session...

    Hibernate 三种状态

    在 Hibernate 中,对象的状态管理是其核心特性之一,主要包括三种状态:瞬时状态(Transient)、持久化状态(Persistent)以及游离状态(Detached)。本文将详细阐述这三种状态的特点及其转换机制。 #### 二、瞬时...

    hibernate--3.Hibernate数据持久化(通过 Session 操纵对象)

    首先,我们需要理解Session在Hibernate中的角色。Session是Hibernate的核心接口之一,它负责对象的持久化操作,比如保存、更新、删除和检索对象。Session对象就像一个临时的工作区域,用于在应用程序和数据库之间...

    Hibernate中的实体状态及转换

    首先,我们要了解Hibernate定义的三种实体状态: 1. **临时状态(Transient)**:当我们在程序中通过`new`关键字创建一个实体对象时,它默认处于临时状态。此时,对象未被Hibernate管理,即使对象包含了主键ID,如果...

    Hibernate三种状态和Session常用的方法

    Hibernate三种状态和Session常用的方法 Hibernate 作为一个...理解 Hibernate 中的三种状态和 Session 中的常用方法是非常重要的。只有深入了解这些机制,我们才能更好地使用 Hibernate 框架来开发高效的应用程序。

    hibernate相关配置 3种状态

    本篇将详细阐述Hibernate中的对象映射关系以及对象的三种状态。 对象映射是Hibernate的核心特性,它通过ORM(Object-Relational Mapping)技术将Java对象与数据库表之间的关系进行映射。Hibernate提供了一种声明式...

    hibernate的核心接口--Session

    - **缓存的同步更新**: 当 Session 清理缓存时,Hibernate 会检查缓存中的对象状态是否发生变化,并同步更新数据库,从而确保数据一致性。 - **缓存相关方法**: - **`flush()`**: 刷新缓存并执行必要的 SQL 语句,...

Global site tag (gtag.js) - Google Analytics