问题描述:

I have NonUniqueObjectException thrown when upgrading my project from Hibernate 3 to Hibernate 4.

I created minimal Hibernate 4 project for testing purposes, and managed to reproduce this exception by:

  • having entity House, and another entity Door that has a composite id that contains House entity

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

  • and then in the same transaction fetching a House and then fetching Door by composite id with:

(Door)session.get(Door.class, doorHousePK)

Here is the hbm file for House:

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

,and the stack trace of the error:

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)

When reverting this minimal project back to Hibernate 3 the exception is gone, and it all works fine.

What is the difference in composite-id handling between Hibernate 3 and Hibernate 4?

How can I make this work in Hibernate 4?

网友答案:

I recently migrated from hibernate 3 to 4 with two tables with composite ids and related to each other by composite foreign key. Exactly same configuration worked fine in both versions. So there is no difference as far as basic concepts about composite-id functionality are concerned.

You should enable debugging for hibernate APIs i.e. set debug level for org.hibernate.* to DEBUG in log properties file to see which SQLs are being fired. That will help you see if any additional/unexpected SQLs are being fired by hibernate.

网友答案:

Make sure your entities, and the objects that make up your composite primary key, have appropriate implementations of hashCode() and equals(). I seem to remember there being some underlying changes in hash-code usage and/or object equality checking between Hibernate 3 and 4.

相关阅读:
Top