`
随枫而弑
  • 浏览: 1457 次
  • 性别: 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
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics