今天做了个测试,写了个测试用例来看看merge与update时控制台打印出来的日志有什么不一样。实体bean很简单,就id和name两个字段,接下来分别给出以下几种测试情形的控制台日志内容:

1. 数据库记录已存在,更改person的name为一个新的name。

merge方法打印出的日志如下:
Hibernate: select person0_.id as id0_0_, person0_.name as name0_0_ from person person0_ where person0_.id=?
Hibernate: update person set name=? where id=?

update方法打印出的日志如下:
Hibernate: update person set name=? where id=?

2. 数据库记录已存在,更改person的name和数据库里对应id记录的name一样的值。

merge方法打印出的日志如下:
Hibernate: select person0_.id as id0_0_, person0_.name as name0_0_ from person person0_ where person0_.id=?
此处相对于第一种情形少了update的动作

update方法打印出的日志如下:
Hibernate: update person set name=? where id=?

3. 数据库记录不存在时,也就是你传的实体bean的ID在数据库没有对应的记录。

merge方法打印出的日志如下:
Hibernate: select person0_.id as id0_0_, person0_.name as name0_0_ from person person0_ where person0_.id=?
Hibernate: insert into person (name) values (?)

如果没有对应的记录,merge会把该记录当作新的记录来插入。此处我很疑惑,因为我传得person实体对象里写明了id值的,它为什么还会做插入的动作呢?

网上朋友的回答:因为没有查到对象没有办法做匹配,不能修改,就往数据库里重新插入一条数据

update方法打印出的日志如下:
Hibernate: update person set name=? where id=?
2009-11-22 20:59:55,359 ERROR [org.hibernate.jdbc.AbstractBatcher] - Exception executing batch:

org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1

以下的内容摘抄自网上:
  当我们使用update的时候,执行完成后,我们提供的对象A的状态变成持久化状态。

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

网上朋友的总结:

merge(oldObj) 操作如下:

if(oldObj没有id) {
      添加操作  
} else {
     if(根据oldObj.id在Hibernate Context中没有找到对象) {
          加载得到newObj;
          if(newObj == null) {
               添加操作
        }

}else{
         newObj
     }
  
    if(oldObj里面的属性 和newObj不一致) {
      更新操作
}

}

Hibernate参考书中hibernate对象三种状态

Hibernate定义并支持下列对象状态(state):

  • 瞬时(Transient) - 由new操作符创建,且尚未与Hibernate
    Session
    关联的对象被认定为瞬时(Transient)的。瞬时(Transient)对象不会被持久化到数据库中,也不会被赋予持久化标识
    (identifier)。 如果瞬时(Transient)对象在程序中没有被引用,它会被垃圾回收器(garbage collector)销毁。
    使用Hibernate
    Session可以将其变为持久(Persistent)状态。(Hibernate会自动执行必要的SQL语句)

  • 持久(Persistent) - 持久(Persistent)的实例在数据库中有对应的记录,并拥有一个持久化标识(identifier)。 持久(Persistent)的实例可能是刚被保存的,或刚被加载的,无论哪一种,按定义,它存在于相关联的Session作用范围内。 Hibernate会检测到处于持久(Persistent)状态的对象的任何改动,在当前操作单元(unit
    of work)执行完毕时将对象数据(state)与数据库同步(synchronize)。 开发者不需要手动执行UPDATE。将对象从持久(Persistent)状态变成瞬时(Transient)状态同样也不需要手动执行DELETE语句。

  • 脱管(Detached) - 与持久(Persistent)对象关联的Session被关闭后,对象就变为脱管(Detached)的。 对脱管(Detached)对象的引用依然有效,对象可继续被修改。脱管(Detached)对象如果重新关联到某个新的Session上, 会再次转变为持久(Persistent)的(在Detached其间的改动将被持久化到数据库)。
    这个功能使得一种编程模型,即中间会给用户思考时间(user think-time)的长时间运行的操作单元(unit of work)的编程模型成为可能。 我们称之为应用程序事务,即从用户观点看是一个操作单元(unit of work)。

Hibernate的merge与update方法的区别的更多相关文章

  1. Save()saveOrUpdate()Hibernate的merge()方法

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

  2. Hibernate的load和get方法的区别

    这次我们聊一下Hibernate3.2 Session加载数据时get和load方法的区别,我总结的如下: 1. 对于get方法,hibernate会确认一下该id对应的数据是否存在,首先在sessi ...

  3. 【hibernate merge】session1.merge(T entity)方法的含义和update方法的区别

    注意:  MERGE语句是SQL语句的一种.在SQL Server.Oracle数据库中可用,MySQL.PostgreSQL中不可用. 1>session1.merge(T entity) 合 ...

  4. hibernate 关于session的update方法

    先看写代码的方法: @Test     public void testUpdate3() {                         Teacher t = new Teacher();   ...

  5. hibernate中load和get方法的区别

    1.读取时机不同(当lazy=true的时候)    load是采用延迟机制(load语句不读库,等使用非主键时才去读库),而get不采用延  迟机制(get语句时马上读库): 2.搜索不到数据时的情 ...

  6. Hibernate Session的delete()方法

    本文介绍Hibernate Session的delete()方法.delete()方法用于从数据库中删除与Java对象对应的记录.对应游离对象和持久化对象,delete语句会做出不同的反应. AD:  ...

  7. [原创]java WEB学习笔记79:Hibernate学习之路--- 四种对象的状态,session核心方法:save()方法,persist()方法,get() 和 load() 方法,update()方法,saveOrUpdate() 方法,merge() 方法,delete() 方法,evict(),hibernate 调用存储过程,hibernate 与 触发器协同工作

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  8. Hibernate merge和update的区别

    今天做了个测试,写了个测试用例来看看merge与update时控制台打印出来的日志有什么不一样.实体bean很简单,就id和name两个字段,接下来分别给出以下几种测试情形的控制台日志内容: 1. 数 ...

  9. hibernate的集中持久化方法的区别

    一.预备知识 在所有之前,说明一下,对于hibernate,它的对象有三种状态,transient.persistent.detached 下边是常见的翻译办法: transient:瞬态或者自由态 ...

随机推荐

  1. jsp中的文件上传

    首先需要有以下的jar包 jsp代码如下: <!-- ${pageContext.request.contextPath}为: "/" + 当前项目名 --> < ...

  2. setInterval与setTimeout

    在自己用canvas画一个时钟时,画秒钟用的是利用图片将重复的线条遮住,但是会出现有两个秒钟线条同时存在,才想起setInterval有那么个坑,查了点资料,记录下,若有不对的或者未写到的点,还请大家 ...

  3. 【CodeBase】PHP转换编码,读写文件/网页内容的防乱码方法

    核心代码: //检查字符串的编码 $charset=mb_detect_encoding($doc,['ASCII','GB2312','GBK','BIG5','UTF8'],TRUE); //字符 ...

  4. 【PHP】详解 $_SERVER 函数中QUERY_STRING和REQUEST_URI、SCRIPT_NAME、PHP_SELF区别

    实例:1.http://localhost/index.php/Home/Home/index.html $_SERVER['QUERY_STRING'] = ""; $_SERV ...

  5. Mongodb内嵌对象关联查询

    db.-10-30T00:00:00Z"),"$lt":ISODate("2018-10-30T23:59:00Z")}, "equip.$ ...

  6. linux下安装VMware出错:Gtk-Message: Failed to load module "canberra-gtk-module"解决方法

    最近又有兴趣在linux下搭建个虚拟机,于是去找了个VMWorkstation,安装的过程中报了两个错误 Gtk-Message: Failed to load module "pk-gtk ...

  7. DiyCode开源项目 AboutActivity分析

    1.首先看一下效果 这是手机上显示的效果: 1.1首先是一个标题栏,左侧一个左箭头,然后一个图标. 1.2然后下方是一个可以滑动的页面. 1.3分成了7个部分. 1.4DiyCode的图标. 1.5然 ...

  8. 产生指定时间区间序列、按指定单位变化时间 python实现

    示例1:给定起始日期和结束日期,如何得到中间的时间序列 import datetime def dateRange(beginDate, endDate): dates = [] dt = datet ...

  9. uoj206 [APIO2016]最大差分

    ref #include "gap.h" #include <iostream> #include <cstdio> using namespace std ...

  10. 502 Bad Gateway 怎么解决?

    出现502的原因是:对用户访问请求的响应超时造成的 服务端解决办法: 1.提高 Web 服务器的响应速度,也即减少内部的调用关系,可以把需要的页面.素材或数据,缓存在内存中,可以是专门的缓存服务器 , ...