`
vking_wang
  • 浏览: 10482 次
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

Hibernate.update()、merge()及引申

 
阅读更多

http://www.hibernate-training-guide.com/merge.html

update()方法存在的问题:

In session, Hibernate guarantees no two Persistent objects represent the same row. Again, this guarantee no

longer holds with Detatched objects. In fact, this problem can create very unwanted consequences. Explore
the code below.
Hibernate保证同一session中不会出现两个持久化对象指向同一数据库行。但对于游离对象,则没有这种保证。这个问题会导致意想不到的结果,例如:

Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
BallPlayer p1 = (BallPlayer)session.get(BallPlayer.class, 1L);
transaction.commit();
session.close();
//p1 is now detached.
session = sessionFactory.openSession();
transaction = session.beginTransaction();
BallPlayer p2 = (BallPlayer)session.get(BallPlayer.class, 1L);
//Oops!  p2 represents the same persistent row as p1.
//When an attempt to reattach p1 occurs, an exception is thrown
session.update(p1);
transaction.commit();
session.close();


This code throws an exception when an attempt to reattach the Detached object at p1 is made.

Exception in thread "main" org.hibernate.NonUniqueObjectException: a
different object with the same identifier value was already associated
with the session: [com.intertech.domain.BallPlayer#1]
at
org.hibernate.engine.StatefulPersistenceContext.checkUniqueness
(StatefulPersistenceContext.java:613)
...



This is because Hibernate is trying to reinforce the guarantee that only a single instance of a Persistent object
exist in memory.

why merge?

The merge operation, helps to deal with this situation.

Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
BallPlayer p1 = (BallPlayer)session.get(BallPlayer.class, 1L);
transaction.commit();
session.close();
//p1 is now detached.
session = sessionFactory.openSession();
transaction = session.beginTransaction();
BallPlayer p2 = (BallPlayer)session.get(BallPlayer.class, 1L);
BallPlayer p3 = (BallPlayer) session.merge(p1);
if (p2 == p3) {
  System.out.println("They're equal");
}
transaction.commit();
session.close();


The merge() method is a little complex and works differently depending on what is in/out of the persistence context.

Hibernate will first check whether a Persistent instance of that type already exists in the persistent context. It uses the object identifiers to check on this existence.

If another instance exists, it copies the state of the Detached object (p1 above) into the existing Persistence object (p2 above).此时p1仍为detached?

If no other instance exists, Hibernate just reattaches the Detached object.应该是创建了一个新对象,而p1仍为detached


In the example above, p2==p3 and one Persistent object exists. In the example below, two Persistent objects
now exist and p2!=p3

Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
BallPlayer p1 = (BallPlayer)session.get(BallPlayer.class, 3L);
transaction.commit();
session.close();
//p1 is now detached.
session = sessionFactory.openSession();
transaction = session.beginTransaction();
BallPlayer p2 = (BallPlayer)session.get(BallPlayer.class, 1L);
BallPlayer p3 = (BallPlayer) session.merge(p1);
if (p2 == p3) {
  System.out.println("They're equal");
}
System.out.println(p2);
System.out.println(p3);
transaction.commit();
session.close();




A complete diagram of the lifecycle now makes sense, given a description of the states and methods that

transition the objects between states.


看到一个说法:

当我们使用update的时候,执行完成后,我们提供的对象A的状态变成持久化状态。
  但当我们使用merge的时候,执行完成,我们提供的对象A还是脱管状态,hibernate或者new了一个B,或者检索到 一个持久对象B,并把我们提供的对象A的所有的值拷贝到这个B,执行完成后B是持久状态,而我们提供的A还是托管状态。


而按照上图,merge之后 A是变为持久化状态了,并非总是托管状态?



关于Hibernate的几种更新方法:


一、预备知识

对于hibernate,它的对象有三种状态,transient、persistent、detached

transient:瞬态或者自由态
(new DeptPo(1,”行政部”,20,”行政相关”),该po的实例和session没有关联,该po的实例处于transient)


persistent:持久化状态
(和数据库中记录想影射的Po实例,它的状态是persistent, 通过get和load等得到的对象都是persistent)


detached:脱管状态或者游离态

和session脱离关联


(1)当通过get或load方法得到的po对象它们都处于persistent,但如果执行delete(po)时(但不能执行事务),该po状态就处于detached, (表示和session脱离关联),因delete而变成游离态可以通过save或saveOrUpdate()变成持久态
(2)当把session关闭时,session缓存中的persistent的po对象也变成detached
因关闭session而变成游离态的可以通过lock、save、update变成持久态
持久态实例可以通过调用 delete()变成脱管状态。
通过get()或load()方法得到的实例都是持久化状态的。
脱管状态的实例可以通过调用lock()或者replicate()进行持久化。


save()和persist()将会引发SQL的INSERT,delete()会引发SQLDELETE,
而update()或merge()会引发SQL UPDATE。对持久化(persistent)实例的修改在刷新提交的时候会被检测到,它也会引起SQL UPDATE。
saveOrUpdate()或者replicate()会引发SQLINSERT或者UPDATE


二、save 和update区别

把这一对放在第一位的原因是因为这一对是最常用的。
save的作用是把一个的对象保存
update是把一个脱管状态的对象或自由态对象(一定要和一个记录对应)更新到数据库


三、update 和saveOrUpdate区别

这个是比较好理解的,顾名思义,saveOrUpdate基本上就是合成了save和update,而update只是update。

引用hibernate reference中的一段话来解释他们的使用场合和区别
通常下面的场景会使用update()或saveOrUpdate():
程序在第一个session中加载对象,接着把session关闭
该对象被传递到表现层
对象发生了一些改动
该对象被返回到业务逻辑层最终到持久层
程序创建第二session调用第二个session的update()方法持久这些改动

saveOrUpdate(po)做下面的事:
如果该po对象已经在本session中持久化了,在本session中执行saveOrUpdate不做任何事
如果savaOrUpdate(新po)与另一个与本session关联的po对象拥有相同的持久化标识(identifier),抛出一个异常

org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [org.itfuture.www.po.Xtyhb#5]

saveOrUpdate如果对象没有持久化标识(identifier)属性,对其调用save() ,否则update() 这个对象


四、persist和save区别

这个是最迷离的一对,表面上看起来使用哪个都行,在hibernate reference文档中也没有明确的区分他们.
这里给出一个明确的区分。(可以跟进src看一下,虽然实现步骤类似,但是还是有细微的差别)
主要内容区别:
1)persist把一个瞬态的实例持久化,但是并"不保证"标识符(identifier主键对应的属性)被立刻填入到持久化实例中,标识符的填入可能被推迟到flush的时候。

2)save, 把一个瞬态的实例持久化标识符,及时的产生,它要返回标识符,所以它会立即执行Sql insert


五、saveOrUpdate,merge和update区别

比较update和merge
update的作用上边说了,这里说一下merge的
如果session中存在相同持久化标识(identifier)的实例,用用户给出的对象覆盖session已有的持久实例
(1)当我们使用update的时候,执行完成后,会抛出异常
(2)但当我们使用merge的时候,把处理自由态的po对象A的属性copy到session当中处于持久态的po的属性中,执行完成后原来是持久状态还是持久态,而我们提供的A还是自由态


六、flush和update区别

这两个的区别好理解
update操作的是在自由态或脱管状态(因session的关闭而处于脱管状态)的对象//updateSQL
flush是操作的在持久状态的对象。
默认情况下,一个持久状态的对象的改动(包含set容器)是不需要update的,只要你更改了对象的值,等待hibernate flush就自动更新或保存到数据库了。hibernate flush发生在以下几种情况中:
1, 调用某些查询的和手动flush(),session的关闭、SessionFactory关闭结合 get()一个对象,把对象的属性进行改变,把资源关闭。
2,transaction commit的时候(包含了flush)


七、lock和update区别

update是把一个已经更改过的脱管状态的对象变成持久状态
lock是把一个没有更改过的脱管状态的对象变成持久状态(针对的是因Session的关闭而处于脱管状态的po对象,不能针对因delete而处于脱管状态的po对象)


对应更改一个记录的内容,两个的操作不同:


update的操作步骤是:
(1)属性改动后的脱管的对象的修改->调用update


lock的操作步骤是:
(2)调用lock把未修改的对象从脱管状态变成持久状态-->更改持久状态的对象的内容-->等待flush或者手动flush


八、clear和evcit的区别

clear完整的清除session缓存
evcit(obj)把某个持久化对象从session的缓存中清空。


分享到:
评论

相关推荐

    管理层宏观经济认知与企业违...mergedata.dta

    管理层宏观经济认知与企业违...mergedata.dta

    Hibernate中的merge使用详情解说

    Hibernate merge 使用详情解说 在 Hibernate 中,merge 方法是非常重要的一个方法,它能够帮助开发者轻松地处理数据的更新和插入操作。那么,merge 方法到底如何工作的呢?下面,我们将对 merge 方法进行详细的解释...

    004.araxis merge 2016(绿色版)

    004.araxis merge 2016(绿色版)004.araxis merge 2016(绿色版)004.araxis merge 2016(绿色版)

    Hibernate中的merge使用详情解说.docx

    在Java的ORM框架Hibernate中,`merge()`是一个非常重要的操作,它主要用于将游离态或瞬态的对象合并到持久化状态。理解`merge()`的工作原理对于优化数据操作和避免潜在的冲突至关重要。以下是对`merge()`函数的详细...

    Hibernate merge、update与saveOrUpdate方法的区别

    ### Hibernate merge、update与saveOrUpdate方法的区别 在Hibernate框架中,`merge`、`update`与`saveOrUpdate`这三个方法都是用于更新或保存实体对象到数据库中的,但它们之间存在着重要的区别,这些区别主要体现...

    使用Hibernate访问sqlserver数据库

    6. **CRUD操作**: 使用Hibernate的API,我们可以轻松地进行创建(`save()`, `saveOrUpdate()`)、读取(`get()`, `load()`)、更新(`update()`, `merge()`)和删除(`delete()`)操作。例如,创建一个新的用户: `...

    J2EE考试复习试题_struts2_spring_hibernate.doc

    - **Hibernate基本操作**:在Hibernate会话接口中,`delete`方法用于删除实体,`merge`方法用于合并实体,`beginTransaction`方法用于开始事务处理。 - **HQL查询创建**:通过`createQuery`方法创建HQL查询接口,`...

    Hibernate save persist merge探究

    《Hibernate的save、persist、merge深度解析》 在Java企业级开发中,Hibernate作为一款强大的对象关系映射(ORM)框架,极大地简化了数据库操作。本文将深入探讨Hibernate中的save、persist和merge这三个方法,帮助...

    10_hibernate.rar

    例如,Session的save()和saveOrUpdate()用于保存或更新对象,get()和load()用于加载对象,update()和merge()用于更新,而delete()则用于删除。 6. 查询机制 Hibernate支持HQL和Criteria API进行查询。HQL允许我们...

    Araxis.Merge.Professional.v2016.4761 最新版破解版

    Araxis.Merge.Professional.v2016.4761 最新版本的破解版,专业软件工具,非常牛逼的文件比较软件,这是官方windows系统下的最新版本破解文件。 安装步骤:1,先安装Araxis.Merge 2,解压缩破解文件包,将里面的可执行...

    Araxis.Merge.z02

    Araxis.Merge是很好用的代码比较工具,目前已经破解 有3个压缩卷 Araxis.Merge.z01 Araxis.Merge.z02 Araxis.Merge.zip 目前是【Araxis.Merge.z02】

    Araxis.Merge.z01

    Araxis.Merge是很好用的代码比较工具,目前已经破解 有3个压缩卷 Araxis.Merge.z01 Araxis.Merge.z02 Araxis.Merge.zip 目前是【Araxis.Merge.z01】

    Github-volley 最新jar包和源代码 2015.07.28

    merge upstream, process response bodies only when present tweak getCacheKey(), using method and original url, fix #67 #78 add RedirectError, wrong exception for http 301 and 302, fix #51 make ...

    CodeMirror.MergeView如何实现代码的搜索和替换(解决方案).md

    CodeMirror.MergeView如何实现代码的搜索和替换(解决方案).md

    hibernate常见异常

    org.hibernate.id.IdentifierGenerationException 是一种常见的异常,通常是由于 <id> 元素配置不正确所致。<id> 元素缺少其子元素 <generator></generator> 的配置引起。解决方案是检查 <id> 元素的配置,确保其子...

    Hibernate update问题

    当你从数据库加载一个对象,修改其属性,然后调用`update()`方法,Hibernate会根据对象的状态自动执行相应的SQL UPDATE语句。然而,如果对象不在Session缓存中,`update()`方法可能会失效,因为Hibernate无法跟踪...

    关于keras中keras.layers.merge的用法说明

    在Keras库中,`keras.layers.merge`是用于合并两个或多个层的输出,它在旧版本的Keras中被广泛使用。然而,随着Keras的发展,这个模块已经被简化和重构,现在的版本中,合并操作通常通过`concatenate`函数来完成。...

    Araxis.Merge.Professional.v2011.4074

    Merge.exe是该软件的主执行程序,用户通过运行这个文件来启动Araxis Merge Professional。merge2011_Win32_4074.msi文件则是Windows系统的安装包,通过这个安装程序,用户可以在Windows操作系统上部署和配置Araxis ...

    Araxis.Merge

    Araxis.Merge是很好用的代码比较工具,目前已经破解 有3个压缩卷 Araxis.Merge.z01 Araxis.Merge.z02 Araxis.Merge.zip 目前是【Araxis.Merge.zip】

    hibernate常见问题及处理.doc

    4. `org.hibernate.id.IdentifierGenerationException: ids for this class must be manually assigned before calling save():` 此异常意味着在尝试保存对象前,对象的主键没有被正确设置。通常,这是由于在映射...

Global site tag (gtag.js) - Google Analytics