a different object with the same identifier value was already associat
- 问题:这个著名的托管态update更新异常
org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated withthe session
- 早先的发生场景:
几乎所有搞过OrMapping持久化程序的开发者都多多少少碰到过这个异常.
这个异常通常发生在一个session 内对同一个数据库对象生成了多个(经常是load(id)/get(id)一个,又new+setId(id)一个),然后又对其进行了update()或者save() .
从业务逻辑的角度,经常发生在修改/更新的操作中.
- 早先的发生原因和解决手段:
经常是session忘记关闭,或忘记commit(),造成本该分为两个session的,合为了一个session,就出现了此异常.
解决手段也很简单,通过session关闭和事务,把相同的操作对象从session级别或者事务级别上分隔开.在两个操作之间session.clear();
- 现在问题的新变化:
- hibernate3.0以后,getCurrentSession()技术的出现,session pool的出现,session不再需要手动open,也不需要手动关闭,反而使问题复杂化
- spring TransactionManager的出现,使问题更复杂
各种Manger Bean, DAO bean里打开了spring事务管理, spring事务又定义了各种操作隔离机制,比如:
"一个在事务下的方法,调用另一个方法,则另一个方法不再开事务,而是涵盖在调用它的方法的事务之下"
"一个在事务下的方法,调用另一个方法,另一个方法建立新事务,父方法的事务暂停,待另一个方法执行完毕,才继续事务".
3. 以struts2 web 框架为代表的一些扩展功能,使问题更复杂
典型的比如struts2 的domain Model (域模型)传参. JSP直接向Action的实例变量对象的属性赋值.如果实例属性存在就直接setter,如果实例属性不存在就自动new 实例
如果这个domain Model是一个实体bean,如果你通过JSP页面set了它的id,或者之前就已经将其持久化了,这就更复杂了.
4. 如spring OpenSessionInViewFilter的出现,用于解决LAZYInitialization延迟加载问题
把session的周期交给servlet filter来管理,每当有request进来,就打开一个session,response结束之后才关闭它,这样可以让session存在于整个servlet request请求周期中
还有许多技术,都或多或少的产生的影响,上面的1-4是最典型的.
- a different object with the same identifier value was already associated withthe session 问题的解决:
其实我没有特别好的解决办法,问题本身也是见仁见智的,需要针对不同场景不同业务逻辑随机应变.本文只是探讨性的文章,属于开放性质的.
从我的经验来说,我倾向于从两方面解决:
1. session方面
从程序的角度,多分析问题,找到session的开始和结束点.
不过说句实话,这真的很难,因为现在的代码越来越框架化,模块化,封装得越来越深,session根本不暴露在业务层之外, 操作经常要上溯到很高层的父类,尤其当和事务挂钩时,更是复杂. 而且现在session的底层操作也越来越晦涩,基于池操作的,基于ThreadLocal操作的,基于JTA的.
2.从update()方面
目前比较普遍的观点,用merge()方法解决是一个比较"傻瓜"的解决办法.
JSR-220里对session.merge()方法的描述:
Copy the state of the given object onto the persistent object with the same identifier.
将给定对象的state(状态,即实例属性)拷贝给到具有相同id的持久化对象
If there is no persistent instance currently associated with the session, it will be loaded. Return the persistent instance.
如果当前没有持久化对象关联到session,当前对象会被加载为持久化对象,并(在update后)返回持久化对象
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.
如果给定实例还没存盘,就存一份copy,并且(这份)copy返回作为新的持久化对象.而给定的对象不会再关联到session
简单总结:
merge()会用"拷贝状态copy the state",也就是属性赋值的直接方法,完成相同id对象的更新,实际就是把内容克隆过去.
如果是一个新的对象实例,merge()实际就等同于save()和persist()
但与save()和persist()不同,merge()完成后,其操作的对象是托管态.
a different object with the same identifier value was already associat的更多相关文章
- a different object with the same identifier value was already associated with the session:
hibernate操作: 实例化两个model类,更新时会提示 a different object with the same identifier value was already assoc ...
- [转]解决a different object with the same identifier value was already associated with the session错误
1.a different object with the same identifier value was already associated with the session. 错误原因:在h ...
- a different object with the same identifier value was already associated with the session:错误;
当出现a different object with the same identifier value was already associated with thesession时,一般是因为在h ...
- org.hibernate.NonUniqueObjectException: a different object with the same identifier value was alread---------程序报错
今天遇到了这个问题: org.hibernate.NonUniqueObjectException: a different object with the same identifier value ...
- 解决a different object with the same identifier value was already associated with the session错误
[转]解决a different object with the same identifier value was already associated with the session错误 这个错 ...
- a different object with the same identifier value was already associated with **(ssh异常转)
Hibernate:a different object with the same identifier value was already associated with ...异常解决 今天 ...
- a different object with the same identifier value was already associated withthe session异常解决方案
异常信息: org.hibernate.NonUniqueObjectException: a different object with the same identifier value was ...
- hibernate中一种导致a different object with the same identifier value was already associated with the session错误方式及解决方法
先将自己出现错误的全部代码都贴出来: hibernate.cfg.xml <?xml version="1.0" encoding="UTF-8"?> ...
- Hibernate Error: a different object with the same identifier value was already associated with the session
在执行Hibernate的Update操作时,报错:a different object with the same identifier value was already associated w ...
随机推荐
- Apache HttpClient
HpptClient特性 1. 基于标准.纯净的java语言.实现了Http1.0和Http1.1 2. 以可扩展的面向对象的结构实现了Http全部的方法(GET, POST, PUT, DELETE ...
- 获取OpenCV中RotatedRect的绝对角度
opencv中RotatedRect的angle这个成员变量总是诡异的不同寻常(http://stackoverflow.com/questions/15956124/minarearect-angl ...
- SpringJDBC
<!-- JdbcTemplate:最基础的springJDBC模板,这个模板支持最简单的jdbc数据库访问功能以及简单的索引参数查询 NamedParameterJdbcTemplate:使用 ...
- 文件 FIFO队列
<?php /** * Filefifo.php 文件型FIFO队列 */ class Filefifo { /** * $_file_data, 数据文件的路径 */ private $_fi ...
- [物理学与PDEs]书中的错误指出
记号意义: P--Page, 第几页; L--Line, 顺数第几行; LL--Last Line, 倒数第几行. P 64 L 1 ``15)'' should be ``14)''. P 70 L ...
- keil中的串口调试:
keil中串口的虚拟调试信息在通过View-serial windows-#usart1/2/3/4/debug(printf)可以看到.当然也可以通过虚拟串口VSPD+串口调试助手在外部实现,方法如 ...
- 在PHPstorm编辑器中配置git环境
在phpstorm编辑器中配置git环境,使得编程人员从git仓库中提交代码,克隆代码,,,更佳便利快捷,有利于提高项目的质量和效率 工具/原料 phpstorm编辑器,git客户端 win7或w ...
- Coding.net 代码管理快速入门
当项目创建好了之后,我们该如何上传代码到 coding 上呢? Coding 网站使用“ Git 仓库”(类似 github )来管理代码. 其操作原理在于:利用 git 服务,将本地的项目目录下的文 ...
- js实现未知宽高的元素在指定元素中垂直水平居中
js实现未知宽高的元素在指定元素中垂直水平居中:本章节介绍一下如何实现未知宽高的元素在指定元素下实现垂直水平居中效果,下面就以span元素为例子,介绍一下如何实现span元素在div中实现水平垂直居中 ...
- Xcode5创建自己的静态库详解
首先声明: 本人屌丝一枚,如有不对不妥之处,请大牛指正! 1.静态库工程的建立: Xcode New一个新的project,选择IOS下面的Framework&Library,下面有一个Coc ...