看了一篇关于Hibernate对象中各个操作的区别分析和状态转化,觉得挺细致,特转一次,以便深入记忆,大概文意如下:
一、对象状态:
hibernate,它的对象有三种状态,transient、persistent、detached
下边是常见的翻译办法:
transient:瞬态或者自由态
persistent:持久化状态
detached:脱管状态或者游离态
脱管状态的实例可以通过调用save()、persist()或者saveOrUpdate()方法进行持久化。
持久化实例可以通过调用
delete()变成脱管状态。通过get()或load()方法得到的实例都是持久化状态的。
脱管状态的实例可以通过调用
update()、0saveOrUpdate()、lock()或者replicate()进行持久化。
save()和persist()将会引发SQL的INSERT,delete()会引发SQLDELETE,
而update()或merge()会引发SQLUPDATE。对持久化(persistent)实例的修改在刷新提交的时候会被检测到,
它也会引起SQLUPDATE。saveOrUpdate()或者replicate()会引发SQLINSERT或者UPDATE
二、save
和update区别
把这一对放在第一位的原因是因为这一对是最常用的。
save的作用是把一个新的对象保存
update是把一个脱管状态的对象保存
三,update
和saveOrUpdate区别
这个是比较好理解的,顾名思义,saveOrUpdate基本上就是合成了save和update
引用hibernate
reference中的一段话来解释他们的使用场合和区别
通常下面的场景会使用update()或saveOrUpdate():
程序在第一个session中加载对象
该对象被传递到表现层
对象发生了一些改动
该对象被返回到业务逻辑层
程序调用第二个session的update()方法持久这些改动
saveOrUpdate()做下面的事:
如果对象已经在本session中持久化了,不做任何事
如果另一个与本session关联的对象拥有相同的持久化标识(identifier),抛出一个异常
如果对象没有持久化标识(identifier)属性,对其调用save()
如果对象的持久标识(identifier)表明其是一个新实例化的对象,对其调用save()
如果对象是附带版本信息的(通过<version>或<timestamp>)
并且版本属性的值表明其是一个新实例化的对象,save()它。
否则update() 这个对象
四,persist和save区别
这个是最迷离的一对,表面上看起来使用哪个都行,在hibernate
reference文档中也没有明确的区分他们.
这里给出一个明确的区分。(可以跟进src看一下,虽然实现步骤类似,但是还是有细微的差别)
这里参考
http://opensource.atlassian.com/projects/hibernate/browse/HHH-1682
中的一个说明:
---------------------------------------------------------------------------------
I
found that a lot of people have the same doubt. To help to solve this issue
I'm quoting Christian Bauer:
"In case anybody finds this
thread...
persist() is well defined. It makes a
transient instance persistent. However,
it doesn't guarantee that the
identifier value will be assigned to the persistent
instance immediately,
the assignment might happen at flush time. The spec doesn't say
that, which
is the problem I have with persist().
persist() also guarantees that it will not
execute an INSERT statement if it is
called outside of transaction
boundaries. This is useful in long-running conversations
with an extended
Session/persistence context.A method like persist() is required.
save() does not guarantee the same, it returns
an identifier, and if an INSERT
has to be executed to get the identifier
(e.g. "identity" generator, not "sequence"),
this INSERT happens
immediately, no matter if you are inside or outside of a transaction. This is
not good in a long-running conversation with an extended Session/persistence
context."
---------------------------------------------------------------------------------
简单翻译一下上边的句子的主要内容:
1,persist把一个瞬态的实例持久化,但是并"不保证"标识符被立刻填入到持久化实例中,标识符的填入可能被推迟
到flush的时间。
2,persist"保证",当它在一个transaction外部被调用的时候并不触发一个Sql
Insert,这个功能是很有用的,
当我们通过继承Session/persistence
context来封装一个长会话流程的时候,一个persist这样的函数是需要的。
3,save"不保证"第2条,它要返回标识符,所以它会立即执行Sql
insert,不管是不是在transaction内部还是外部
五,saveOrUpdateCopy,merge和update区别
首先说明merge是用来代替saveOrUpdateCopy的,这个详细见这里
http://www.blogjava.net/dreamstone/archive/2007/07/28/133053.html
然后比较update和merge
update的作用上边说了,这里说一下merge的
如果session中存在相同持久化标识(identifier)的实例,用用户给出的对象的状态覆盖旧有的持久实例
如果session没有相应的持久实例,则尝试从数据库中加载,或创建新的持久化实例,最后返回该持久实例
用户给出的这个对象没有被关联到session上,它依旧是脱管的
重点是最后一句:
当我们使用update的时候,执行完成后,我们提供的对象A的状态变成持久化状态
但当我们使用merge的时候,执行完成,我们提供的对象A还是脱管状态,hibernate或者new了一个B,或者检索到
一个持久对象B,并把我们提供的对象A的所有的值拷贝到这个B,执行完成后B是持久状态,而我们提供的A还是托管状态
六,flush和update区别
这两个的区别好理解
update操作的是在脱管状态的对象
而flush是操作的在持久状态的对象。
默认情况下,一个持久状态的对象是不需要update的,只要你更改了对象的值,等待hibernate
flush就自动
保存到数据库了。hibernate flush发生再几种情况下:
1,调用某些查询的时候
2,transaction
commit的时候
3,手动调用flush的时候
七,lock和update区别
update是把一个已经更改过的脱管状态的对象变成持久状态
lock是把一个没有更改过的脱管状态的对象变成持久状态
对应更改一个记录的内容,两个的操作不同:
update的操作步骤是:
(1)更改脱管的对象->调用update
lock的操作步骤是:
(2)调用lock把对象从脱管状态变成持久状态-->更改持久状态的对象的内容-->等待flush或者手动flush
参考内容:
http://www.blogjava.net/iamtin/archive/2006/03/06/33910.aspx
http://opensource.atlassian.com/projects/hibernate/browse/HHH-1682
http://www.redsaga.com/hibernate-ref/3.x/zh-cn/html/objectstate.html
先来点概念:
在Hibernate中,最核心的概念就是对PO的状态管理。一个PO有三种状态:
1、未被持久化的VO
此时就是一个内存对象VO,由JVM管理生命周期
2、已被持久化的PO,并且在Session生命周期内
此时映射数据库数据,由数据库管理生命周期
3、曾被持久化过,但现在和Session已经detached了,以VO的身份在运行
这种和Session已经detached的PO还能够进入另一个Session,继续进行PO状态管理,此时它就成为PO的第二种状态了。这种PO实际上是跨了Session进行了状态维护的。
在传统的JDO1.x中,PO只有前面两种状态,一个PO一旦脱离PM,就丧失了状态了,不再和数据库数据关联,成为一个纯粹的内存VO,它即使进入一个新的PM,也不能恢复它的状态了。
Hibernate强的地方就在于,一个PO脱离Session之后,还能保持状态,再进入一个新的Session之后,就恢复状态管理的能力,但此时状态管理需要使用session.update或者session.saveOrUpdate,这就是Hibernate
Reference中提到的“requires a slightly different programming model ”
现在正式进入本话题:
简单的来说,update和saveOrUpdate是用来对跨Session的PO进行状态管理的。
假设你的PO不需要跨Session的话,那么就不需要用到,例如你打开一个Session,对PO进行操作,然后关闭,之后这个PO你也不会再用到了,那么就不需要用update。
因此,我们来看看:
代码
Foo foo=sess.load(Foo.class,id);
foo.setXXX(xxx);
sess.flush();
sess.commit();
PO
对象
foo
的操作都在一个
Session
生命周期内完成,因此不需要显式的进行
sess.update(foo)
这样的操作。
Hibernate
会自动监测到
foo
对象已经被修改过,因此就向数据库发送一个
update
的
sql
。当然如果你非要加上
sess.update(foo)
也不会错,只不过这样做没有任何必要。
而跨
Session
的意思就是说这个
PO
对象在
Session
关闭之后,你还把它当做一个
VO
来用,后来你在
Session
外面又修改了它的属性,然后你又想打开一个
Session
,把
VO
的属性修改保存到数据库里面,那么你就需要用
update
了。
代码
// in the first session
Cat cat = (Cat) firstSession.load(Cat.class,
catId);
Cat potentialMate = new Cat();
firstSession.save(potentialMate);
// in a higher tier of the
application
potentialMate.setXxx(xxx);
cat.setMate(potentialMate);
// later, in a new session
secondSession.update(cat); // update
cat
secondSession.update(mate); // update
mate
cat和mate对象是在第一个session中取得的,在第一个session关闭之后,他们就成了PO的第三种状态,和Session已经detached的PO,此时他们的状态信息仍然被保留下来了。当他们进入第二个session之后,立刻就可以进行状态的更新。但是由于对cat的修改操作:cat.setMate(potentialMate);
是在Session外面进行的,Hibernate不可能知道cat对象已经被改过了,第二个Session并不知道这种修改,因此一定要显式的调用secondSession.update(cat);
通知Hibernate,cat对象已经修改了,你必须发送update的sql了。
所以update的作用就在于此,它只会被用于当一个PO对象跨Session进行状态同步的时候才需要写。而一个PO对象当它不需要跨Session进行状态管理的时候,是不需要写update的。
再谈谈saveOrUpdate的用场:
saveOrUpdate
和
update
的区别就在于在跨
Session
的
PO
状态管理中,
Hibernate
对
PO
采取何种策略。
例如当你写一个DAOImpl的时候,让cat对象增加一个mate,如下定义:
代码
public void addMate(Cat cat, Mate mate)
{
Session session = ...;
Transacton tx = ...;
session.update(cat);
cat.addMate(mate);
tx.commit();
session.close();
};
显然你是需要把Hibernate的操作封装在DAO里面的,让业务层的程序员和Web层的程序员不需要了解Hibernate,直接对DAO进行调用。
此时问题就来了:上面的代码运行正确有一个必要的前提,那就是方法调用参数cat对象必须是一个已经被持久化过的PO,也就是来说,它应该首先从数据库查询出来,然后才能这样用。但是业务层的程序员显然不知道这种内部的玄妙,如果他的业务是现在增加一个cat,然后再增加它的mate,他显然会这样调用,new一个cat对象出来,然后就addMate:
代码
Cat cat = new Cat();
cat.setXXX();
daoimpl.addMate(cat,mate);
但是请注意看,这个
cat
对象只是一个
VO
,它没有被持久化过,它还不是
PO
,它没有资格调用
addMate
方法,因此调用
addMate
方法不会真正往数据库里面发送
update
的
sql
,这个
cat
对象必须先被
save
到数据库,在真正成为一个
PO
之后,才具备
addMate
的资格。
你必须这样来操作:
代码
Cat cat = new Cat();
cat.setXXX();
daoimpl.addCat(cat);
daoimpl.addMate(cat, mate);
先持久化cat,然后才能对cat进行其他的持久化操作。因此要求业务层的程序员必须清楚cat对象处于何种状态,到底是第一种,还是第三种。如果是第一种,就要先save,再addMate;如果是第三种,就直接addMate。
但是最致命的是,如果整个软件分层很多,业务层的程序员他拿到这个cat对象也可能是上层Web应用层传递过来的cat,他自己也不知道这个cat究竟是VO,没有被持久化过,还是已经被持久化过,那么他根本就没有办法写程序了。
所以这样的DAOImpl显然是有问题的,它会对业务层的程序员造成很多编程上的陷阱,业务层的程序员必须深刻的了解他调用的每个DAO对PO对象进行了何种状态管理,必须深刻的了解他的PO对象在任何时候处于什么确切的状态,才能保证编程的正确性,显然这是做不到的,但是有了saveOrUpdate,这些问题就迎刃而解了。
现在你需要修改addMate方法:
代码
public void addMate(Cat cat, Mate mate)
{
Session session = ...;
Transacton tx = ...;
session.saveOrUpdate(cat);
cat.addMate(mate);
tx.commit();
session.close();
};
如上,如果业务层的程序员传进来的是一个已经持久化过的PO对象,那么Hibernate会更新cat对象(假设业务层的程序员在Session外面修改过cat的属性),如果传进来的是一个新new出来的对象,那么向数据库save这个PO对象。
BTW: Hibernate此时究竟采取更新cat对象,还是save
cat对象,取决于unsave-value的设定。
这样,业务层的程序员就不必再操心PO的状态问题了,对于他们来说,不管cat是new出来的对象,只是一个VO也好;还是从数据库查询出来的的PO对象也好,全部都是直接addMate就OK了:
代码
daoimple.addMate(cat, mate);
这便是saveOrUpdate的作用。
使用
get()
或
load()
方法取得
id
为
1
的数据
;
如果未能发现相符合的数据,则
get()
方法会返回
null
,而
load()
方法会丢出
ObjectNotFoundException
,在进阶的应用中,
load()
方法可以返回代理对象,并可充分利用缓冲机制。
在
Hibernate 3
中,取消了
find()
方法,您必须透过
Query
或
Criteria
来进行数据查询
分享到:
相关推荐
- 对象状态:Hibernate定义了四种对象状态:瞬时态、持久态、脱管态和临时态,理解这些状态有助于正确处理对象的生命周期。 5. **持久化操作**:通过Hibernate的API,可以方便地进行对象的持久化操作,如保存新...
3. **Query和Criteria API**:提供强大的查询能力,允许开发者用面向对象的方式编写查询,支持HQL(Hibernate Query Language)和 Criteria 查询,类似于SQL但更贴近Java对象。 4. **缓存机制**:Hibernate支持一级...
在Java开发领域,Hibernate作为一款强大的对象关系映射(ORM)框架,被广泛应用于数据库操作。深入理解Hibernate的源码对于提升开发技能、优化代码性能至关重要。本文将详细阐述通过三种查询方式跟踪Hibernate源码的...
- Hibernate定义了三种对象状态:瞬时态、持久态和脱管态。理解这些状态对于有效地管理对象非常重要。 5. **CRUD操作**: - 使用Hibernate 3 API,可以方便地实现创建(Create)、读取(Read)、更新(Update)和...
通过Hibernate,开发者可以将数据库操作转化为对Java对象的操作,减少了直接编写SQL的需要。Hibernate支持多种数据库,包括MySQL,它提供了透明的数据持久化,事务管理和查询语言HQL,使得数据操作更加便捷。 ...
通过Hibernate,开发者可以将数据库操作转化为对Java对象的操作,减少了直接编写SQL语句的工作量。在本示例中,你将看到如何定义实体类、配置Hibernate的SessionFactory、以及如何使用HQL(Hibernate查询语言)进行...
3. **持久化类和对象状态**:Hibernate管理对象的生命周期,包括瞬时态、持久态、托管态和脱管态。通过Session接口,对象可以在不同状态间转换。 4. **会话(Session)**:Session是与数据库交互的核心接口,负责...
Spring作为核心框架,负责依赖注入(DI)和面向切面编程(AOP),SpringMVC用于处理HTTP请求并展示结果,而Hibernate则是主流的ORM(对象关系映射)工具,帮助开发者管理数据库操作。下面将详细介绍SSH整合的关键...
6. **实体状态管理**:Hibernate管理的对象状态包括瞬时态、持久态、托管态和游离态,源码中可以探索这些状态的转换过程,以及`PersistenceContext`如何维护对象状态。 7. **连接池管理**:Hibernate依赖于连接池来...
Hibernate 是一个开源的Java平台上的对象关系映射(ORM)框架,它允许开发者将数据库操作转化为对Java对象的操作,从而简化了数据持久化的复杂度。这个“Hibernate3[1].2中文参考文档.chm”是针对Hibernate 3.2版本...
Hibernate的核心概念包括实体(Entity)、持久化类(Persistent Class)、对象状态(Object State)和会话(Session)。实体是业务逻辑中的对象,它们在数据库中对应为表。持久化类是包含@Entity注解的Java类,用于...
**Hibernate**是一个强大的对象关系映射(ORM)框架,它负责数据持久层,即处理数据库相关的操作。Hibernate通过提供透明的会话管理和事务管理等特性,极大地简化了与数据库交互的过程。 将这三个框架有效地整合在...
Hibernate是一个强大的对象关系映射(ORM)框架,它允许开发者用Java对象来操作数据库,而无需直接编写SQL语句。Struts则是Java EE平台上的一个MVC(Model-View-Controller)框架,用于构建可维护、可扩展的Web应用...
Struts2和Hibernate是两种非常...这个项目的代码应该包含以上各个模块的实现,通过学习和分析这些代码,开发者可以深入了解如何在实际项目中整合Struts2和Hibernate,提高开发效率,同时掌握电子商务网站的开发流程。
在权限角色系统中,Hibernate负责对象关系映射(ORM),将Java对象转化为数据库中的记录,反之亦然。通过ORM,开发者可以专注于业务逻辑,而无需关心底层SQL语句的编写。 4. **Maven**:Maven是Java项目管理和综合...
其次,Hibernate是对象关系映射(ORM)框架,它将数据库操作转化为对Java对象的操作。在本项目中,Hibernate负责管理博客系统的数据模型,比如博客文章、用户信息等。通过编写Hibernate的实体类和配置映射文件(hbm....
Hibernate是一个对象关系映射(ORM)框架,它消除了Java程序与SQL数据库之间的直接交互,将数据库操作转化为对Java对象的操作。Hibernate提供了强大的查询语言HQL和 Criteria API,支持对象的持久化、级联操作、缓存...
在论坛系统中,Hibernate帮助开发者将数据库操作转化为对Java对象的操作,避免了繁琐的SQL编写。例如,通过配置XML映射文件,可以将用户信息、帖子、回复等实体类与数据库表对应起来,实现数据的增删改查。 **...
4. **物联网与Hibernate结合**:在物联网项目中,开发者可能使用Hibernate来管理设备状态、用户信息、传感器数据等数据库操作。例如,当传感器收集到环境数据时,这些数据可以通过Hibernate框架存入数据库,以便后续...
Hibernate则是一个对象关系映射(ORM)框架,能够将数据库操作转化为对Java对象的操作,简化了数据库访问的复杂性。这两个框架结合使用,能够高效地构建出一个功能完备、易于维护的选课系统。 在选课系统的设计和...