Hibernate: composite-id with key-many-to-one generating java.lang.stackoverflow error

user2170297 picture user2170297 · Mar 14, 2013 · Viewed 9.3k times · Source

I've been trying to map the following tables into Hibernate with hbm files:

CREATE TABLE
    additional_info
    (
        info_id SMALLINT,
        book_id INT,
        desc VARCHAR(32) NULL,
        CONSTRAINT additional_info_pk PRIMARY KEY (info_id, book_id),
        CONSTRAINT additional_info_fk FOREIGN KEY (info_id, book_id) REFERENCES info (id, book_id)
    );

CREATE TABLE
    info
    (
        id SMALLINT,
        book_id INT,
        item_name VARCHAR(32),
        CONSTRAINT pk_info PRIMARY KEY (id, book_id ),
        CONSTRAINT fk_info FOREIGN KEY (book_id ) REFERENCES book (book_id)        );

As you see, they both share the same 2-field primary key - which is, in turn, also a foreign key from additional_info to info.

This is how hibernateTools defined the relation (additional_info hbm):

<composite-id name="id" class="AdditionalInfoId">
    <key-many-to-one name="info" class="Info">
        <column name="info_id" />
        <column name="book_id" />
    </key-many-to-one>
</composite-id>

And in info's hbm:

<one-to-one name="additionalInfo" class="AdditionalInfo"></one-to-one>

Using this approach, I keep getting a java.lang.stackoverflow error. I've been searching and trying different mappings/alternatives combinations, but without success - since I don't have much experience with hibernate, it's more like wild guessing (and most are using annotations these days). Some suggest to use <id> and <generator> but I couldn't find an example with two fields being used to link the one to one relationship, being both PK and FK.

My classes are all Serializable and have the equals and hashCode methods generated automatically too.

I also don't understand why the "key-many-to-one". This should be a one to one relationship. I read it's not a good idea using composite-id with this key-many-to-one, but I failed to implement an alternative that works.

Any insight would be greatly appreciated.

Thanks a lot!

PS: a piece of the stack trace:

java.lang.StackOverflowError
    at java.lang.Integer.equals(Integer.java:747)
    at org.hibernate.util.EqualsHelper.equals(EqualsHelper.java:10)
    at org.hibernate.type.NullableType.isEqual(NullableType.java:214)
    at org.hibernate.type.NullableType.isEqual(NullableType.java:210)
    at org.hibernate.type.AbstractType.isEqual(AbstractType.java:116)
    at org.hibernate.engine.EntityKey.equals(EntityKey.java:97)
    at java.util.HashMap.get(HashMap.java:305)
    at org.hibernate.engine.StatefulPersistenceContext.getEntity(StatefulPersistenceContext.java:322)
    at org.hibernate.impl.SessionImpl.getEntityUsingInterceptor(SessionImpl.java:478)
    at org.hibernate.event.def.DefaultLoadEventListener.loadFromSessionCache(DefaultLoadEventListener.java:436)
    at org.hibernate.event.def.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:338)
    at org.hibernate.event.def.DefaultLoadEventListener.load(DefaultLoadEventListener.java:139)
    at org.hibernate.event.def.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:195)
    at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:103)
    at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java:878)
    at org.hibernate.impl.SessionImpl.internalLoad(SessionImpl.java:846)
    at org.hibernate.type.EntityType.resolveIdentifier(EntityType.java:557)
...

Answer

Carlos picture Carlos · Apr 23, 2013

If you define bidirectional references one of them should be lazy in order to avoid StackOverflow.

Hope it helps you.