Hibernate保存对象出现 org.hibernate.NonUniqueObjectExce

简介: Hibernate保存对象出现 org.hibernate.NonUniqueObjectExce

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.


相关文章
|
SQL 缓存 Java
Hibernate对象状态之间的神奇转换
Hibernate对象状态之间的神奇转换
|
3月前
|
SQL Java 数据库连接
Hibernate 是一款开源 ORM(对象关系映射)框架,封装了 JDBC,允许以面向对象的方式操作数据库,简化了数据访问层的开发。
Hibernate 是一款开源 ORM(对象关系映射)框架,封装了 JDBC,允许以面向对象的方式操作数据库,简化了数据访问层的开发。通过映射机制,它可以自动处理对象与数据库表之间的转换,支持主流数据库,提高了代码的可移植性和可维护性。其核心接口包括 SessionFactory、Session 和 Transaction 等,通过它们可以执行数据库的 CRUD 操作。配置方面,需在项目中引入 Hibernate 及数据库驱动依赖,并创建 `hibernate.cfg.xml` 配置文件来设置数据库连接和 Hibernate 行为参数。
46 1
|
3月前
|
Java 数据库连接 数据库
|
3月前
|
Java 数据库连接 数据库
|
5月前
|
缓存 Java 数据库连接
解析Hibernate与JPA:Java对象的数据库化之旅
【6月更文挑战第25天】在Java企业开发中,Hibernate和JPA提供优雅的数据持久化方案。Hibernate是JPA规范的强大ORM实现,简化对象与数据库映射。配置环境后,通过@Entity注解定义实体类映射表,如`User`类映射"users"表。利用JPA的EntityManager执行查询和更新,如JPQL查询及对象更新。事务管理和性能优化是关键,确保数据完整性和应用性能。本文揭示了Hibernate与JPA的最佳实践,助开发者从容应对数据持久化。
44 0
|
5月前
|
存储 Java 数据库连接
深入探索Hibernate与JPA:Java对象与数据库表的桥梁
【6月更文挑战第25天】Java ORM如Hibernate和JPA简化了数据库交互。在电商系统案例中,JPA注解如`@Entity`、`@Table`、`@Id`定义了对象-表映射。Hibernate利用这些定义实现持久化,如`Session.save()`保存用户对象至数据库,降低了复杂性并提升了开发效率。
48 0
|
6月前
|
SQL Java 关系型数据库
Hibernate - 对象关系映射文件(*.hbm.xml)详解
Hibernate - 对象关系映射文件(*.hbm.xml)详解
254 1
|
6月前
|
SQL Java 数据库连接
Hibernate - QBC和本地SQL对象检索详解
Hibernate - QBC和本地SQL对象检索详解
62 0
|
6月前
|
SQL Java 数据库连接
Hibernate - HQL对象检索详解
Hibernate - HQL对象检索详解
53 0