您好,欢迎来到华佗小知识。
搜索
您的当前位置:首页hibernate中的merge()方法

hibernate中的merge()方法

来源:华佗小知识

Hibernate提供有save()、persist()、savaOrUpdate()和merge()等方法来提供插入数据的功能。前三者理解起来较后者容易一些,而merge()方法从api中的介绍就可以看出它是最复杂的,因此要特别留意一下。

Hibernate的api中关于merge()方法的原文

从参数说明来看,merge()方法的参数应该是一个处于托管状态的实例对象,而返回值则是一个持久化对象。但是这里的参数并不是一定要是托管状态的对象,它还可以是瞬态和持久化的实例对象。正因如此,才使merge方法变得复杂化。

merge()方法的作用

Hibernate中有一个常见错误:A different object with the same identifier value was already associated with the session,即在一个session中存在两个不同的实体却有着相同的身份标签(主键)是会报错的,这时为了避免这种错误就可以使用Hibernate提供的merge()方法。

merge()方法的使用特性

1.new一个对象并设置ID时,这个对象会被当作游离态处理,在使用merge时,如果在数据库中不能能找到这条记录,则使用insert将数据插入;如果在数据库中找到这条记录,则使用update将数据更新。

2.new一个对象没有设置ID时,这个对象会被当作瞬态处理,在使用merge时会根据实体类的主键生成策略保存这条数据。

3.使用merge存储到数据库的对象,其本身不会转变为持久态对象。

Hibernate中三态的补充

1.瞬态:通过Java关键字new的实体类对象,不和Session实例关联并且在数据库中没有和瞬态对象关联的记录,此时的对象还没有纳入Hibernate的缓存管理中。

2.持久态: 已经被保存进数据库的实体对象,还存于Hibernate的缓存管理之中。

3.游离态(脱管态):持久态对象脱离了Hibernate的缓存管理后就会变成游离态,游离态对象与瞬态对象的最大区别在于,游离态对象在数据库中可能存在一条与之对应的记录,而瞬态对象则不会在数据库中存在与之对应的记录,简而言之就是游离态对象比瞬态对象多了一个ID属性。

代码实际校验

经实际代码的检验,从merge()方法产生的效果来看,它和saveOrUpdate()方法相似,因此虽然上面提到是因为参数状态的不同造成复杂化,但是这里我并不打算分参数的不同状态来理解merge()方法,而是根据参数有无id或id是否已经存在来理解merge()方法。个人认为这样更容易理解,而且从执行他们两个方法而产生的sql语句来看是一样的。

1.参数实例对象没有提供id或提供的id在数据库中不存在,这时merge将执行插入操作,产生的sql语句如下:

Hibernate: select max(uid) from user
Hibernate: insert into hibernate1.user (name, age, uid) values (?, ?, ?)

2. 参数实例对象的id在数据库中已经存在,此时又有两种情况。

①如果对象有改动,则执行更新操作,产生sql语句有:

Hibernate: select user0_.uid as uid0_0_, user0_.name as name0_0_, user0_.age as age0_0_ from hibernate1.user user0_ where user0_.uid = ? 
Hibernate: update hibernate1.user set name = ?, age = ? where uid = ?

②如果对象无改动,则执行查询操作,产生的语句有:

Hibernate: select user0_.uid as uid0_0_, user0_.name as name0_0_, user0_.age as age0_0_ from hibernate1.user user0_ where user0_.uid = ?

而不管哪种情况,merge的返回值都是一个持久化的实例对象,虽然对于参数而言不会改变它的状态。

总结

虽然从功能上来说,merge()方法与saveOrUpdate()方法类似,但是他们依然是有区别的。

比如有这样一种情况:我们先通过session的get方法得到一个对象u,然后关掉session,再打开一个session并执行saveOrUpdate(u)。此时我们可以看到抛出异常:Exception in thread "main" org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session,即在session缓存中不允许有两个id相同的对象。这时若使用merge方法则不会异常,其实从merge的中文意思(合并)我们就可以理解了。

 

"匆匆忙忙,恍恍惚惚,慌慌张张。"

转载于:https://www.cnblogs.com/yanggb/p/11268377.html

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- huatuo0.cn 版权所有 湘ICP备2023017654号-2

违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务