`
随枫而弑
  • 浏览: 1552 次
  • 性别: Icon_minigender_1
文章分类
社区版块
存档分类
最新评论

连续使用merge和update梳理

    博客分类:
  • java
阅读更多

前几天,公司的老司机在群里发了一个问题供大家探讨:

 

刚遇到一个hibernate的问题,项目框架是struts2+ spring +hibernate3问题,在action层,分别调用了2service 方法,比如叫aService.mergeEntity(entity)bService.updateEntity(entity);

参数都有一个entity对象这个 entity hibernate的一个entity

然后呢在第一个aService方法里 调用了hibernatemerge(entity);

然后在第二个bService方法里调用了hibernateupdate(entity);

那么第二个bService方法会不会报错,如果报错,是什么错误,怎么解决?

 

我的回答:分为2种情况。当entity是瞬时态的时候(即entity没有id),由于merge的机制关系(可参考http://blog.csdn.net/hurahura/article/details/51933454http://blog.csdn.net/ml5271169588/article/details/6734981),merge生成了另一个持久态对象entity2并在事务结束时将其持久化至数据库中,但entity本身仍是瞬时态的,这时对瞬时态对象执行update就会报一个对象id为空的错误;当entity是游离态时(有id),不会报错。

 

之后老司机说了,他碰到的情况是entity已经手动set了一个id(这里我和他对于手动set id后对象是否是游离态产生了分歧,但与此题关系不大暂不讨论),在update时然后报了session中已有一个id相同的对象的错误。

 

那么我是不服的,在我看来当entityid时,虽然merge方法从数据库中取出了一个id相同的持久态对象entity2,但由于事务边界是在service层的,aService的方法执行完之后事务提交、session关闭、entity2从持久态变为游离态,再执行bService方法时,新的session中没有同id的持久态对象了,就不会报错。

 

为了证明我的观点,我就选用了手头上一个SSH项目开始了我的实验:

 

情景一:entity为瞬时态,即没有id

可以看到,此时与我的第一段回答相同,是由于merge的机制导致的错误。

 

情景二:entity set了一个数据库中已存在的id

此时居然报错了!且与老司机所说的错误相同:session中已存在了一个id相同的对象,为了证实此错误是由于session没有关闭,merge产生的entity2仍是持久态(即仍与session关联),我又设置了

 

情景三:在同一个service方法下对entity进行mergeupdate

可以看到,与情景二错误相同,那么应该可以证实是session没有关闭引起的错误(其实这里是不严谨的,仅是猜测,因为我对于底层的session不熟悉,不知道如何手动关闭T^T)。之后证实spring确实配置了OpenSessionInView方法使session保持开启(关于OpenSessionInView可以参考

http://www.iteye.com/topic/32001)

 

情景四:entity set了一个数据库中不存在的id

 

entityid在数据库中不存时,从打印出来的hibernate语句中可以看到,mergeselect对象无果时去insert了,但因为我的主键策略是sequencemerge产生的entity2identity并不同,所以没有报错。(这里算是抓住老司机的一个漏洞,扳回半城)。

 

解决方案:第二个update方法用merge代替,因为第二个merge会找到第一个merge产生的entity2(此时entity2还在session中,仍是持久态)作为entity的持久态,就不会像update一样报出session中已存在了一个id相同的对象的错误了。这也是merge最主要的用法(多数情况下我们都用saveOrUpdate)。

 

至此,所有情况分析完毕。虽然看似是一段明显不合理的程序,但分析出来的错误原因却出人意料,其中也涉及到了对象状态、merge机制、spring管理下的session、主键策略等多个知识点。所以就算是一小段程序,要想写好,也需要我们对各个细节融会贯通,我要学习的还有很多啊!

  • 大小: 94.5 KB
  • 大小: 71.9 KB
  • 大小: 99.4 KB
  • 大小: 107.8 KB
分享到:
评论

相关推荐

    session中merge和update的区别

    Hibernate中session的merge以及update方法

    Hibernate merge、update与saveOrUpdate方法的区别

    通过上述分析可以看出,`merge`、`update`和`saveOrUpdate`方法在处理实体对象时有不同的行为。选择合适的方法取决于具体的业务场景和需求。例如,在需要更新现有记录时,可以考虑使用`update`或`merge`方法;而在不...

    Merge Into 语句代替InsertUpdate

    非常经典的SQL经验,适合于数据库初学者及长期从事软件开发者

    Merge into的使用详解

    本篇文章将详细介绍`MERGE INTO`的使用,包括两种常见的写法,并通过实例进行说明。 一、`MERGE INTO`的基本语法 `MERGE INTO`语句的基本结构如下: ```sql MERGE INTO target_table USING source_table ON (join...

    oracle merge into的使用

    在Oracle 9i版本中,Merge Into 的引入使得开发者能够同时执行更新(UPDATE)和插入(INSERT)操作,而到了Oracle 10g及后续版本,这一功能得到了进一步增强,提供了更丰富的条件选择和操作选项。 ### 知识点详述:...

    Araxis Merge 使用教程.pdf

    Araxis Merge 软件入门使用教程 Araxis Merge 软件入门使用教程 Araxis Merge 软件入门使用教程 Araxis Merge 软件入门使用教程 pdf

    Hibernate中的merge使用详情解说

    在上面的示例代码中,我们可以看到如何使用 merge 方法来处理数据的更新和插入操作。首先,我们创建了一个新的 Students 对象,并设置了其 ID 和 Name 属性,然后使用 merge 方法将其保存到数据库中。在第二个 ...

    save, saveOrUpdate, persist, merge, update 区别.docx

    在Java的持久化框架Hibernate中,管理对象与数据库之间的交互是通过一系列的方法完成的,其中包括`save()`, `saveOrUpdate()`, `persist()`, `merge()`, 和 `update()`。这些方法各有其特点和适用场景,理解它们的...

    android merge和include简单使用

    在实际使用`merge`和`include`时,有几点需要注意: 1. 当`include`标签用于`merge`标签内时,`merge`会处理`include`的子视图,直接将它们添加到最终的视图树中。 2. 使用`include`时,如果包含的布局中有需要动态...

    Mybatis批量foreach merge into的用法

    首先,需要使用Oracle 9i及其以后版本支持的merge into语句,该语句可以实现insertOrUpdate的功能。然后,使用Mybatis的动态SQL语法foreach循环插入,待插入的实体bean的List通过查询数据库dual形成表。foreach的 ...

    Araxis Merge v6.5/Araxis Merge 2017比对工具

    里面给大家内嵌了Araxis Merge v6.5和Araxis Merge 2017两个版本,并配备了使用说明。 Araxis Merge v6.5:免安装版本,解压直接运行merge.exe即可正常使用(目前好像不支持Win10系统了,但是我同事的win10可以用,...

    android merge 标签使用介绍

    本篇文章将详细介绍`merge`标签的使用方法及其优势。 `merge`标签最初被引入是为了减少视图层次,这是因为在Android系统中,每个视图层级都会带来额外的绘制开销。当我们在一个布局文件中嵌套多个视图时,这些层级...

    WinMerge WinMerge WinMerge

    WinMerge是一款强大的文本和文件比较工具,尤其在IT行业中,它是开发者和版本控制使用者的得力助手。这个软件能够帮助用户高效地对比不同版本的代码或者其他文本文件,从而快速定位和理解版本之间的差异。 首先,...

    Oracle中merge into的使用

    在Oracle数据库中,`MERGE INTO`语句是一种强大的数据操作工具,它允许你在一个步骤中执行更新(UPDATE)和插入(INSERT)操作,从而提高了数据处理的效率和灵活性。这个命令尤其适用于需要同步两个表的数据时,比如...

    Include和merge标签使用

    在Android开发中,`<include>`和`<merge>`标签是两种非常重要的布局组合工具,它们可以帮助开发者提高代码复用性,减少布局嵌套,从而优化应用性能和UI设计。让我们深入探讨这两种标签的使用方法及其优化布局的作用...

    Android中include和merge标签的使用

    总结来说,`include`和`merge`是Android布局设计中的强大工具,通过合理使用它们,开发者可以创建更灵活、高效且易于维护的布局结构。理解并熟练掌握这两个标签的使用,对于提升Android应用的用户体验和开发效率具有...

    oracle Merge 函数.doc

    Merge 函数的使用方式有三种:只更新不插入、只插入不更新和既插入也更新。 Merge 函数的基本用法 Merge 函数的基本语法结构为: ```sql MERGE INTO 目标表 USING 来源表 ON (条件) WHEN MATCHED THEN 更新操作 ...

    使用BULK COLLECT, MERGE 语句提高sql执行效率

    详细介绍了使用 BULK COLLECT 进行批量操作 提高sql的执行效率 使用MERGE INTO USING 一条sql搞定 新增和修改 使用connect by 进行递归树查询

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

    在Java的ORM框架Hibernate中,`merge()`是一个非常重要的操作,它主要用于将游离态或瞬态的对象合并到持久化状态。...在设计和实现业务逻辑时,理解并正确使用`merge()`对于维护数据库的正确性至关重要。

    android中include和merge标记的区别和使用

    在Android开发中,布局设计是应用...通过理解和合理使用`include`和`merge`,开发者可以有效地管理布局文件,提高代码的可维护性,并优化应用的性能。在实际项目中,应根据具体需求选择合适的方法,平衡功能与性能。

Global site tag (gtag.js) - Google Analytics