将项目从Hibernate 3升级到Hibernate 4时,抛出了NonUniqueObjectException。 我创建了最小的Hibernate 4项目用于测试目的,并设法通过以下方式重现此异常:
拥有实体House,以及具有包含House实体
的复合ID的另一个实体Door<class dynamic-insert="true" dynamic-update="true" name="entity.Door" select-before-update="true" table="DOOR">
<composite-id name="id" class="DoorHousePK">
<key-many-to-one class="entity.House" column="HOUSEID" name="house"/>
<key-property column="DOORID" name="doorId" type="string"/>
</composite-id>
然后在同一事务中获取一个House,然后通过复合ID获取Door:
(门)session.get(Door.class,doorHousePK)
以下是House的hbm文件:
<class dynamic-insert="true" dynamic-update="true" name="entity.House" select-before-update="true" table="HOUSE">
<id column="ID" name="id" type="int"/>
<property column="squarefeet" name="squareFeet" not-null="false" type="int"/>
<property column="address" length="255" name="address" not-null="false" type="string"/>
<property column="color" length="32" name="color" not-null="false" type="string"/>
<property column="description" name="description" not-null="false" type="materialized_clob"/>
</class>
,以及错误的堆栈跟踪:
INFO: HHH000327: Error performing load command : org.hibernate.NonUniqueObjectException: A different object with the same identifier value was already associated with the session : [entity.House#1]
Exception in thread "main" org.hibernate.NonUniqueObjectException: A different object with the same identifier value was already associated with the session : [entity.House#1]
at org.hibernate.engine.internal.StatefulPersistenceContext.checkUniqueness(StatefulPersistenceContext.java:617)
at org.hibernate.event.internal.AbstractReassociateEventListener.reassociate(AbstractReassociateEventListener.java:74)
at org.hibernate.event.internal.DefaultLockEventListener.onLock(DefaultLockEventListener.java:95)
at org.hibernate.internal.SessionImpl.fireLock(SessionImpl.java:774)
at org.hibernate.internal.SessionImpl.fireLock(SessionImpl.java:767)
at org.hibernate.internal.SessionImpl.access$1800(SessionImpl.java:176)
at org.hibernate.internal.SessionImpl$LockRequestImpl.lock(SessionImpl.java:2491)
at org.hibernate.loader.plan.exec.internal.EntityLoadQueryDetails$EntityLoaderRowReader.addKeyManyToOnesToSession(EntityLoadQueryDetails.java:263)
at org.hibernate.loader.plan.exec.internal.EntityLoadQueryDetails$EntityLoaderRowReader.readRow(EntityLoadQueryDetails.java:247)
at org.hibernate.loader.plan.exec.process.internal.ResultSetProcessorImpl.extractResults(ResultSetProcessorImpl.java:129)
at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:138)
at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:102)
at org.hibernate.loader.entity.plan.AbstractLoadPlanBasedEntityLoader.load(AbstractLoadPlanBasedEntityLoader.java:186)
at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:4126)
at org.hibernate.event.internal.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:503)
at org.hibernate.event.internal.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:468)
at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:213)
at org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:275)
at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:151)
at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1070)
at org.hibernate.internal.SessionImpl.access$2000(SessionImpl.java:176)
at org.hibernate.internal.SessionImpl$IdentifierLoadAccessImpl.load(SessionImpl.java:2551)
at org.hibernate.internal.SessionImpl.get(SessionImpl.java:955)
当将这个最小的项目还原回Hibernate 3时,异常消失了,一切正常。
Hibernate 3和Hibernate 4之间的复合id处理有什么区别? 如何在Hibernate 4中完成这项工作?
答案 0 :(得分:0)
我最近从hibernate 3迁移到了4个带有复合ID的表,并且通过复合外键相互关联。完全相同的配置在两个版本中都运行良好。因此,就复合id功能的基本概念而言,没有区别。
您应该为hibernate API启用调试,例如将org.hibernate。*的调试级别设置为日志属性文件中的DEBUG,以查看正在触发的SQL。这将帮助您查看hibernate是否正在触发任何其他/意外的SQL。
答案 1 :(得分:0)
确保您的实体以及构成复合主键的对象具有hashCode()和equals()的适当实现。我似乎记得Hibernate 3和4之间的哈希码使用和/或对象相等性检查存在一些潜在的变化。