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

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

merge
Object merge(Object object)
throws HibernateException
Copy the state of the given object onto the persistent object with the same identifier. If there is no persistent instance currently associated with the session, it will be loaded. Return the persistent instance. If the given instance is unsaved, save a copy of and return it as a newly persistent instance. The given instance does not become associated with the session. This operation cascades to associated instances if the association is mapped with cascade="merge"
The semantics of this method are defined by JSR-220.
Parameters:
object - a detached instance with state to be copied
Returns:
an updated persistent instance
Throws:
HibernateException

从参数说明来看,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的中文意思(合并)我们就可以理解了。

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

hibernate中的merge()方法的更多相关文章

  1. Hibernate中的GetCurrentSession()方法

    从3.0.1版本开 始,Hibernate增加了SessionFactory.getCurrentSession()方法. 采用getCurrentSession()创建的session在commit ...

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

    merge的作用是:新new一个对象,如果该对象设置了ID,则这个对象就当作游离态处理:                                       当ID在数据库中不能找到时,用up ...

  3. Hibernate中Session.save()方法的返回值是什么

    public   Serializable   save(Object   object)     Parameters:     object   -   a   transient   insta ...

  4. 【hibernate】Hibernate中save, saveOrUpdate, persist, merge, update 区别

    Hibernate Save hibernate save()方法能够保存实体到数据库,正如方法名称save这个单词所表明的意思.我们能够在事务之外调用这个方法,这也是我不喜欢使用这个方法保存数据的原 ...

  5. Hibernate中易错地方的总结

    1.Hibernate中的配置文件要放在src下,注意不能放在包目录下 2.Hibernate中@Before   @After方法不能再普通的类里用,只有在专门的JUnit测试用例里面用. 3.使用 ...

  6. Hibernate中的HQL语言

    一.HQL语言简介 HQL全称是Hibernate Query Language,它提供了是十分强大的功能,它是针对持久化对象,直接取得对象,而不进行update,delete和insert等操作.而 ...

  7. Hibernate中对象的三种状态以及Session类中saveOrUpdate方法与merge方法的区别

    首先,用一张图说明一个对象,在Hibernate中,在调用了不同方法之后对象所处的不同状态 在Hibernate中,一个对象的状态可以被分为如图所示的三种 Transient:瞬时对象,该对象在数据库 ...

  8. Hibernate中Session的save()、update()、merge()、lock()、saveOrUpdate()和persist()方法有什么区别?

    Hibernate的对象有三种状态:瞬态.持久态和游离态.游离状态的实例可以通过调用save().persist()或者saveOrUpdate()方法进行持久化:脱管状态的实例可以通过调用 upda ...

  9. hibernate中save()、get()、load()、update()、saveorupdate()、merge()等方法

    1.save()方法 直接传个user对象 session.save(user); 2.get()方法和load()方法 get(): 传id        session.get(UserInfo. ...

随机推荐

  1. 小程序--log居中 失焦获取表单中的值

    value="{{username}}" 绑定值 值在js文件的data中 pa==>Vant-Weap中表单中的值,不是双向绑定的. 你获取值后, 值并没有在对用的data ...

  2. Python导入运行的当前模块报错

    引言 今天遇到了一个奇怪的现象,简单举个栗子: 文件结构如下:

  3. CentOS 7怎么删除mariadb

    参考链接:https://www.cnblogs.com/ytkah/p/10876824.html

  4. [译]Vulkan教程(13)图形管道基础之Shader模块

    [译]Vulkan教程(13)图形管道基础之Shader模块 Shader modules Unlike earlier APIs, shader code in Vulkan has to be s ...

  5. flash的几种模式Normal Mode、DUAL Mode、Quad Mode的概念和区别

    概念 1. 标准SPI 标准SPI通常就称SPI,它是一种串行外设接口规范,有4根引脚信号:clk , cs, mosi, miso 2. Dual SPI 它只是针对SPI Flash而言,不是针对 ...

  6. 将vue项目部署在Linux的Nginx下,并设置为局域网内访问

    1. 下载 wget http://nginx.org/download/nginx-1.12.2.tar.gz 2. 解压缩 tar -zxvf linux-nginx-1.12.2.tar.gz ...

  7. 02-java性能调优-JVM内存模型详解

    JVM整体结构与内存模型之间的关系 JVM整体结构图如下: 先贴一个代码: package com.jvm.jvmCourse2; public class Math { public static ...

  8. 一起学Android之Handler

    概述 在Android开发中,有主线程(UI线程)和工作线程(Worker线程)之分,两个线程是相互独立的,并不能相互访问(主线程主要负责UI的更新,不能进行耗时的操作,工作线程主要负责耗时的操作,但 ...

  9. Python 你见过三行代码的爬虫吗

    ------------恢复内容开始------------ 每次讲爬虫的时候都会从“发送请求” 开始讲,讲到解析页面的时候可能大部分读者都会卡住,因为这部分确实需要一点XPATH或者CSS选择器的前 ...

  10. PHPStudyLite启动不成功怎么办

    点击环境端口检测 有端口打开则关闭 一切正常后重新开启