简体   繁体   中英

Hibernate 4 composite-id NonUniqueObjectException

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM