Hibernate save 在 session 中已存在相同 OID(主键) 的对象,会出现异常,详细内容如下:

Exception in thread "main" org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [com.unmi.LoanDetail#1]
at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:168)
at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:121)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:187)
at org.hibernate.event.def.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:33)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:172)
at org.hibernate.event.def.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:27)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:70)
at org.hibernate.impl.SessionImpl.fireSave(SessionImpl.java:535)
at org.hibernate.impl.SessionImpl.save(SessionImpl.java:523)
at org.hibernate.impl.SessionImpl.save(SessionImpl.java:519)
at com.unmi.Test.main(Test.java:44)

重现以上错误的代码如下(去除了事物控制的代码行):

Session session = HibernateSessionFactory.getSession();
// 加载OID为1L的对象,会被放在session缓存中
LoanDetail detail = (LoanDetail)session.get(LoanDetail. class , 1L );
// new 一个OID也为1L的临时对象
LoanDetail newDetail = new LoanDetail( 1L );
newDetail.setSubjectId( 1000L );
// 持久化一个临时对象,试图放在session的缓存中,因OID冲突出现异常
session.save(newDetail);
// 执行saveOrUpdate同样会出现以上的异常
// session.saveOrUpdate(newDetail);

解决方法:
1) 如果用的 hibernate 2, 需要在get/load/query到持久化对象,赋上新的属性值,再 save/update/saveOrupdate.
对以上代码就是:不能 new 一个session中已存在OID的对象,直接

detail.setSubjectId(1000L);
session.save(detail);
session.save() //一个持久化对象时,会转化成update调用。

2) 使用 hibernate 3 的 merge 方法. session.merge(newDetail)即可,它会在 session 缓存中找到持久化对象,把新对象的属性赋过去,再保存原session中的持久化对象。
如果在session或数据库中没有的对象,用merge方法的话,它也能够帮你把记录 insert 到表中,相当于 save 方法。

上面是一个简单的例子,实际业务中可能是经过一番复杂的操作后自己也很难搞清楚 new 的一个新对象在 session/数据库中是否已存在。所以第一种方法你需要清楚你的每一个对象状态,第二种方法在 hibernate 3 中就比较通用一些。

附 hibernate javadoc 对 session.merge() 方法的注释:

Copy the state of the given object onto the persistent object with the same identifier. If there is no persistent instance currently associated with the session, it will be loaded. Return the persistent instance. 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. This operation cascades to associated instances if the association is mapped with cascade="merge".The semantics of this method are defined by JSR-220.

Hibernate保存对象出现 org.hibernate.NonUniqueObjectExce相关推荐

  1. atitit.spring hibernate的事务机制 spring不能保存对象的解决

    atitit.spring hibernate的事务机制 spring不能保存对象的解决 sessionFactory.openSession() 不能..log黑头马sql语言.. sessionF ...

  2. Hibernate之对象关系映射文件

    一.对象关系映射文件 POJO类和关系数据库之间的映射可以用一个XML文档来定义 在运行时Hibernate将根据这个映射文件来生成各种SQL语句 映射文件的拓展名为 .hbm.xml 1.映射文件说 ...

  3. hibernate保存失败_Hibernate:保存与保存并保存或更新

    hibernate保存失败 save和saveOrUpdate之间的区别是什么或save和persist之间的区别是任何Hibernate面试中常见的面试问题,就像Hibernate中get和load ...

  4. java对象持久化技术_Java对象持久化技术Hibernate 一

    Hibernate是Java应用和关系数据库之间的桥梁,它负责Java对象和关系数据之间的映射.Hibernate内部封装了通过JDBC访问数据库的操作,向上层应用提供了面向对象的数据访问API.在J ...

  5. Hibernate bean 对象配制文件

    Hibernate bean 对象配制文件 class Person{private int pid; } 1 配制主键 <?xml version="1.0" encodi ...

  6. Hibernate持久化对象生命周期之实战探索

    正所谓"工欲善其事,必先利其器",我陈述过自己的从业经历,因为并非IT科班出身,刚入职有很多不懂,由于需要快速开发,所以在还未对Hibernate有仔细的认识前,我就兼任新老系统的 ...

  7. 10、Hibernate的对象检索策略

    - 立即检索策略 - 延迟检索策略 - 左外连接检索策略 - 每种检索策略的适用范围 - 在程序中显式指定左外连接检索策略 表字段之间的对应关系 1.运行Session的方法 List custome ...

  8. hibernate中对象的状态有三种

    一,首先hibernate中对象的状态有三种:瞬态.游离态和持久态,三种状态转化的方法都是通过session来调用,瞬态到持久态的方法有save().saveOrUpdate().get().load ...

  9. Hibernate旅程(五)Hibernate映射--基本类映射和对象关系映射

    回想一些我们在没有学习ssh的时候,我们建立数据库的表时,首先是数据库建模E-R图,然后再通过实体模型来建立关系模型,再建立相应的表.实体间存在三种关系,一对一,一对多(或者说多对一),多对多.而如今 ...

最新文章

  1. 呼和浩特机器人光缆设备_工业机器人最坚固配件,虐它千万次,性能依旧
  2. spring核心配置文件引入外部properties文件和另外的xml配置文件
  3. 一级学科和二级学科_在多学科团队中工作的6个障碍(以及如何解决这些问题)
  4. mysql客户端重置密码是多少,mysql重置root密码
  5. 面试官:请讲一下Redis主从复制的功能及实现原理
  6. Filter过滤器除去部分URL链接
  7. UI设计素材|底部导航设计的黄金法则
  8. 【C++:类和对象】处理一个线性表,动态产生线性存储空间,并实现线性表的部分操作
  9. Python实现问卷星表单机刷
  10. 自然语言处理NLP星空智能对话机器人系列:深入理解Transformer自然语言处理 Semantic Role Labeling (SRL).
  11. reverse-for-the-holy-grail-350 攻防世界
  12. 一键加速去不掉加锁的_三种方法让你的Service不被“一键加速”和系统杀掉
  13. 初中数学老师计算机培训反思,初中数学特级教师培训会学习心得体会
  14. SQL中destinct的用法
  15. 每次启动虚拟机都要重装虚拟机的操作系统
  16. MATLAB 绘制堆叠柱状图
  17. DSRC通信协议标准
  18. 关于存储优化型实例和大型数据仓库EC2实例选型
  19. 道路矢量下载 转shp格式
  20. JetBrains 家族所有 IDE 主题配色方案 下载安装方法

热门文章

  1. 扩展欧几里得算法与模乘逆元的程序
  2. linux 下的两种软件安装方式 —— 源码(编译、安装),编译好的二进制(直接安装)
  3. TensorFlow 实战(一)—— 交叉熵(cross entropy)的定义
  4. matlab 格式化文本文件的解析
  5. 常见信号的模拟仿真(matlab)(spike signal)
  6. 《墨子》 —— 兼爱与非攻
  7. word 的使用(六)—— 常用功能
  8. Source Insight 的使用
  9. 【剑指 offer】(十)—— 二进制形式 1 的个数
  10. hive 操作(五)——常用内置函数