-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 3 posts ] 
Author Message
 Post subject: previously-persisted List data lost on update
PostPosted: Fri Jun 08, 2007 2:53 pm 
Newbie

Joined: Fri Jun 08, 2007 2:23 pm
Posts: 3
I've got an odd problem where data in a List that was once persisted gets nulled out on an 'update' operation.

For a trivial example, class T1 has a one-to-many relationship with T2, implemented thus:


Code:
T1 t1 = new T1();  //T1's constructor creates a list and adds a T2 to it
t1.nextT2();  //creates another T2 object and appends it to the list;
t1.nextT2();

...etc

here's how they are mapped:

Code:
<class name="T1" table="t1">
    <id name="id" column="t1_id" type="long">
        <generator class="sequence">
            <param name="sequence">t1_seq</param>
        </generator>
    </id>
    <list name="t2s" table="t2" cascade="all">
        <key column="t1_id"/>
        <index column="idx"/>
        <one-to-many class="T2"/>
    </list>
</class>

<class name="T2" table="t2">
    <id name="id" column="t2_id" type="long">
        <generator class="sequence">
            <param name="sequence">t2_seq</param>
        </generator>
    </id>
    <property name="t1Id" column="t1_id" type="long"/>
</class>


My problem is that if I do this:

Code:
Session sess = HibernateUtil.getSession();
T1 t1 = new T1();
t1.nextT2();
sess.save(t1);
t1.nextT2();
t1.nextT2();
t1.nextT2();
sess.update(t1);


What I end up with are 5 new entries in the t2 table, with the first two (at idx 0 & 1) having NULL in the t1_id column. The last three rows (indices 2-4) are populated with the t1_id as they should be.

I've written a test cast which exposes this behavior, and have verified that after the 'save()' and before the 'update()', the t1_id exists for all the new t2 entries. It's only when updating the t1 object that its t2 references which existed prior have their t1_id field nulled out.

Is this a problem with my cascade setting? I've verified this behavior is database independent, as I can produce it in Oracle and PostgreSQL. I'm using Hibernate v. 3.2

I've got the mapping files, the classes, and the test case in an archive and can give it via email if anyone wants to try to reproduce this error. Any help is much appreciated!!!
--Kris


Last edited by jimjamjoh on Fri Jun 08, 2007 3:29 pm, edited 1 time in total.

Top
 Profile  
 
 Post subject: a hack around the problem
PostPosted: Fri Jun 08, 2007 3:26 pm 
Newbie

Joined: Fri Jun 08, 2007 2:23 pm
Posts: 3
OK, so as soon as I posted this, I found a way to hack around the problem by doing the following before my session.update():

Code:
Iterator t2s = t1.getT2s().iterator();
while (t2s.hasNext()) {
    ((T2)t2s.next()).setT1Id(t1.getId());
}


So the obvious problem is that my t1Id property in my T2 objects aren't being set during the initial call to session.save(), even though the foreign key itself is being written, so that when I call update(), hibernate finds that t1Id is null for those T2 objects which are already persisted, and nulls out the database field (blowing away my fkey) accordingly. Eff.

I found some solutions in the Hibernate docs telling me to add 'update' and 'not-null' attributes to the <key> declaration, but I kept throwing ExceptionInInitializerError...the Hibernate config wouldn't even load.


Top
 Profile  
 
 Post subject: nevermind, i solved the problem
PostPosted: Fri Jun 08, 2007 3:46 pm 
Newbie

Joined: Fri Jun 08, 2007 2:23 pm
Posts: 3
A coding error, wouldn't you know.

Here was the composition of my nextT2() method:

Code:
public void nextT2() {
    if (this.t2s == null) {
        this.t2s = new Vector(4);
    }
    this.currentT2 = new T2();
    this.currentT2.setT1Id(this.id);
    this.currentT2.setIndex(this.t2s.size());
    this.t2s.add(this.currentT2);
}


Since the id on my T1 objects is generated from a sequence, they have no id (the id property, type Long, is null) prior to my call to session.save(). So every T2 instantiated before session.save() is getting a null object passed to setT1Id().

So Hibernate's using the T1 list to create new entries in the t2 table (which is why the t1_id fkey gets initially written), but for updating existing t2 table entries, it's going to the associate T2 object and writing sql NULL into fields whose mapped property contains a null object.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 3 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.