• 问题:这个著名的托管态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();

  • 现在问题的新变化:
  1. hibernate3.0以后,getCurrentSession()技术的出现,session pool的出现,session不再需要手动open,也不需要手动关闭,反而使问题复杂化
  2. 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的更多相关文章

  1. 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 ...

  2. [转]解决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 ...

  3. 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 ...

  4. org.hibernate.NonUniqueObjectException: a different object with the same identifier value was alread---------程序报错

    今天遇到了这个问题: org.hibernate.NonUniqueObjectException: a different object with the same identifier value ...

  5. 解决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错误 这个错 ...

  6. 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 ...异常解决 今天 ...

  7. 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 ...

  8. 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"?> ...

  9. 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 ...

随机推荐

  1. Jedis 连接redis超时

    redis默认不允许远程连接 用vi打开Redis服务器的配置文件redis.conf ~ sudo vi /etc/redis/redis.conf #注释bind #bind 127.0.0.1 ...

  2. [JS]鼠标事件穿透的问题

    今天制作登陆窗口的效果时碰到的一个问题,如下: 标签结构如下: <div id="loginFrame"> <form class="loginFram ...

  3. catalan数及笔试面试里那些相关的问题(转)

    一.catalan数由来和性质 1)由来 catalan数(卡塔兰数)取自组合数学中一个常在各种计数问题中出现的数列.以比利时的数学家欧仁·查理·卡塔兰 (1814–1894)命名. 卡塔兰数的一般项 ...

  4. No matching bean of type [xx] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency

    这个看起来很弱爆的问题其实是因为其他的配置文件中已经出现了为xx定义好的注入.如果用@Autowired就会得到上面的错误 , 但是用@Resource的时候就会看到类似下面的错误 Bean name ...

  5. ssh-keygen+ssh-copy-id无密码登录远程LINUX主机(转载)

    From:http://blog.163.com/lgh_2002/blog/static/44017526201011333227161/ 1.创建公钥和私钥 ligh@local-host$ ss ...

  6. php 获取时间今天明天昨天时间戳

    <?php echo "今天:".date("Y-m-d")."<br>";      echo "昨天:&qu ...

  7. USB枚举过程

    1. 枚举是什么?        枚举就是从设备读取一些信息,知道设备是什么样的设备,如何进行通信,这样主机就可以根据这些信息来加载合适的驱动程序.调试USB设备,很重要的一点就是USB的枚举过程,只 ...

  8. [模板总结] Java的一些模板

    快速排序(数组a从小到大,参数1是待排序的数组,参数2是起始下标,参数3是终止下标): static void sort(int [] a, int l,int r){ int m = l+r> ...

  9. Android中通过广播方式调起第三方App

    今天紧急的跟进一个百度视频App无法调起百度贴吧App的问题,当然,这个是只发现是在4.x的android系统下发生,在2.x版本下,一切正常,(其实是3.1及以上的版本都有问题)具体场景为: 1.贴 ...

  10. Skill

    Skill Yasser is an Egyptian coach; he will be organizing a training camp in Jordan. At the end of ca ...