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.  [ 4 posts ] 
Author Message
 Post subject: Updating detached collection fails to persist FK and index
PostPosted: Thu Mar 17, 2005 11:08 pm 
Newbie

Joined: Tue Jan 04, 2005 4:52 pm
Posts: 13
Hibernate version: 2.1.8

Hello All,

I have a server and client database. The server contains the root of my object heirarchy. (A Sample and a Household)

It is passed to the client where the child objects (People and Trips) are attached and persisted into a client database.

Everything works fine for building and persisting the objects in the client database.

However, when I send the object heirarchy back to the server (and reattach to the server database) none of the collection keys/indices are written into the tables. All the other information (entity properties, many-to-one reference) are written properly.

There are no errors or exceptions on the update on the server. I've checked and the keys are correctly written on the client database.


The heirachy is Household has a list of People and each Person has list of Trips.

I have cascade="all-delete-orphan" set for all the lists

Each entity in the heirarchy has a composite ID.

Can anyone provide some hints as to whay this might be happening?

I use a session.saveOrUpdate (Household) to reattach the heirarchy. My custom interceptor (not really relevant to this issue) determines whether an insert or upate is required for each Entity.

Thanks in advance for any help you can provide.

Mapping files for the first level are:

Code:
<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">

<hibernate-mapping
>
    <class
        name="Household"
        table="household"
        dynamic-update="true"
        dynamic-insert="true"
        select-before-update="false"
        optimistic-lock="version"
    >

        <composite-id
            name="ID"
            class="SampleCompositeID"
        >

                     <key-property
                        name="sample"
                        type="java.lang.Long"
                        column="sampleid"
                />

                     <key-property
                        name="entityID"
                        type="java.lang.Long"
                        column="id"
                />

        </composite-id>

        <property
            name="addressChanged"
            type="boolean"
            update="true"
            insert="true"
            access="property"
            column="addressChanged"
        />

        <property
            name="dwellingTypeChanged"
            type="boolean"
            update="true"
            insert="true"
            access="property"
            column="dwellingTypeChanged"
        />

        <property
            name="movedFlagChanged"
            type="boolean"
            update="true"
            insert="true"
            access="property"
            column="movedFlagChanged"
        />

        <property
            name="mailingReceivedChanged"
            type="boolean"
            update="true"
            insert="true"
            access="property"
            column="mailingReceivedChanged"
        />

        <property
            name="phoneNumberChanged"
            type="boolean"
            update="true"
            insert="true"
            access="property"
            column="phoneNumberChanged"
        />

        <property
            name="numberOfPeopleChanged"
            type="boolean"
            update="true"
            insert="true"
            access="property"
            column="numberOfPeopleChanged"
        />

        <property
            name="numberOfVehiclesChanged"
            type="boolean"
            update="true"
            insert="true"
            access="property"
            column="numberOfVehiclesChanged"
        />

        <property
            name="respondentNumberOfPeople"
            type="java.lang.Integer"
            update="true"
            insert="true"
            access="property"
            column="respondentNumberOfPeople"
        />

        <property
            name="phoneNumber"
            type="java.lang.String"
            update="true"
            insert="true"
            access="property"
            column="phoneNumber"
        />

        <property
            name="dwellingType"
            type="java.lang.String"
            update="true"
            insert="true"
            access="property"
            column="dwellingType"
        />

        <property
            name="movedFlag"
            type="java.lang.String"
            update="true"
            insert="true"
            access="property"
            column="movedFlag"
        />

        <property
            name="mailingReceived"
            type="java.lang.String"
            update="true"
            insert="true"
            access="property"
            column="mailingReceived"
        />

        <property
            name="numberOfPeople"
            type="java.lang.Integer"
            update="true"
            insert="true"
            access="property"
            column="numberOfPeople"
        />

        <list
            name="personList"
            lazy="false"
            inverse="false"
            cascade="all-delete-orphan"
        >

              <key
              >
                <column
                    name="fk_householdid"
                />
                <column
                    name="fk_householdsampleid"
                />
              </key>

              <index
                  column="fk_household_index"
              />

              <one-to-many
                  class="Person"
              />

        </list>

        <property
            name="numberOfVehicles"
            type="java.lang.Integer"
            update="true"
            insert="true"
            access="property"
            column="numberOfVehicles"
        />

        <property
            name="persistedOnServer"
            type="boolean"
            update="true"
            insert="true"
            access="property"
            column="persistedOnServer"
        />

        <property
            name="persistedOnClient"
            type="boolean"
            update="true"
            insert="true"
            access="property"
            column="persistedOnClient"
        />

        <!--
            To add non XDoclet property mappings, create a file named
                hibernate-properties-Household.xml
            containing the additional properties and place it in your merge dir.
        -->

    </class>

</hibernate-mapping>



Code:
<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">

<hibernate-mapping
>
    <class
        name="Person"
        table="person"
        dynamic-update="false"
        dynamic-insert="false"
        select-before-update="false"
        optimistic-lock="version"
    >

        <composite-id
            name="ID"
            class="SampleCompositeID"
        >

                     <key-property
                        name="sample"
                        type="java.lang.Long"
                        column="sampleid"
                />

                     <key-property
                        name="entityID"
                        type="java.lang.Long"
                        column="id"
                />

        </composite-id>

        <property
            name="workLocationType"
            type="java.lang.String"
            update="true"
            insert="true"
            access="property"
            column="workLocationType"
        />

        <property
            name="initialOriginLocationType"
            type="java.lang.String"
            update="true"
            insert="true"
            access="property"
            column="initialOriginLocationType"
        />

        <property
            name="schoolLocationType"
            type="java.lang.String"
            update="true"
            insert="true"
            access="property"
            column="schoolLocationType"
        />

        <property
            name="transitPassType"
            type="java.lang.String"
            update="true"
            insert="true"
            access="property"
            column="transitPassType"
        />

        <property
            name="transitPass"
            type="java.lang.String"
            update="true"
            insert="true"
            access="property"
            column="transitPass"
        />

        <property
            name="transitPassChanged"
            type="boolean"
            update="true"
            insert="true"
            access="property"
            column="transitPassChanged"
        />

        <many-to-one
            name="initialOrigin"
            class="LocationDataWrapper"
            cascade="all"
            outer-join="auto"
            update="true"
            insert="true"
            access="property"
        >
            <column
                name="fk_originid"
            />
            <column
                name="fk_originsampleid"
            />
        </many-to-one>

        <property
            name="initialOriginPurpose"
            type="java.lang.String"
            update="true"
            insert="true"
            access="property"
            column="initialOriginPurpose"
        />

        <property
            name="anyTripStatus"
            type="java.lang.String"
            update="true"
            insert="true"
            access="property"
            column="anyTripStatus"
        />


        <property
            name="label"
            type="java.lang.String"
            update="true"
            insert="true"
            access="property"
            column="label"
        />

        <property
            name="age"
            type="java.lang.Integer"
            update="true"
            insert="true"
            access="property"
            column="age"
        />

        <property
            name="genderType"
            type="java.lang.String"
            update="true"
            insert="true"
            access="property"
            column="genderType"
        />

        <property
            name="licenseType"
            type="java.lang.String"
            update="true"
            insert="true"
            access="property"
            column="licenseType"
        />

        <property
            name="employmentType"
            type="java.lang.String"
            update="true"
            insert="true"
            access="property"
            column="employmentType"
        />

        <property
            name="occupationType"
            type="java.lang.String"
            update="true"
            insert="true"
            access="property"
            column="occupationType"
        />


        <property
            name="studentType"
            type="java.lang.String"
            update="true"
            insert="true"
            access="property"
            column="studentType"
        />


        <list
            name="tripList"
            lazy="false"
            inverse="false"
            cascade="all-delete-orphan"
        >

              <key
              >
                <column
                    name="fk_personid"
                />
                <column
                    name="fk_personsampleid"
                />
              </key>

              <index
                  column="fk_person_index"
              />

              <one-to-many
                  class="Trip"
              />

        </list>

        <property
            name="persistedOnServer"
            type="boolean"
            update="true"
            insert="true"
            access="property"
            column="persistedOnServer"
        />

        <property
            name="persistedOnClient"
            type="boolean"
            update="true"
            insert="true"
            access="property"
            column="persistedOnClient"
        />

        <!--
            To add non XDoclet property mappings, create a file named
                hibernate-properties-Person.xml
            containing the additional properties and place it in your merge dir.
        -->

    </class>

</hibernate-mapping>


Top
 Profile  
 
 Post subject:
PostPosted: Fri Mar 18, 2005 1:34 am 
Newbie

Joined: Fri Mar 18, 2005 1:19 am
Posts: 3
I think I'm experiencing the same problem. I'm doing the similar client-side manipulation of objects, however I've been able to reproduce the problem using a server-side only test case. The problem seems to go away when the operations are performed within a Session/transaction.

The code is something like:

Parent p = new Parent();
p.setValue("whatever")
HibernateUtil.store(p); // calls Session.saveOrUpdate()

HibernateUtil.commit();
HibernateUtil.closeSession();
// if the above 2 lines are commented out, all works fine.

Child c = new Child();
c.setValue("whatever");
p.addChild(c); // which also does c.setParent(p);
p.setValue("newValue")'

HibernateUtil.store(p);
HibernateUtil.commit();
HibernateUtil.closeSession();


The result is that the Parent is saved correctly, but the Child is not inserted. The one-to-many relationship specifies cascade=save-update and inverse=false.

Hibernate does access the Child sequence and assign a new ID to the Child; it just does not insert the Child.

Adding a line to store the Child separately also does not seem to help (i.e. HibernateUtil.store(c) -- either before or after storing p).


Top
 Profile  
 
 Post subject:
PostPosted: Sat Mar 19, 2005 3:00 pm 
Newbie

Joined: Fri Mar 18, 2005 1:19 am
Posts: 3
So after some further investigation, this problem seems to be due to Hibernate's handling of detached Collections. (i.e., once the session is closed, the object and its content collections are no longer associated with the session). When you do a Session.update(obj), the object is reassociated with a session, but the contents of the object and its collection are silently assumed to be the current persistent state. And due to that, the content objects are skipped during the update.

If you do a Session.lock(obj, LockMode.UPGRADE) prior to the update(), Hibernate will throw an exception complaining about reassociation of a dirty collection.

If I do the lock() after the update(), (as I have seen suggested in other posts), then I get an Oracle fetch out-of-sequence error (ORA-01002).

So.... what we need is some reasonable way to work around this. How do we persist the state of a collection back into the DB after it has been detached?


Top
 Profile  
 
 Post subject:
PostPosted: Thu Mar 24, 2005 2:01 am 
Newbie

Joined: Fri Mar 18, 2005 1:19 am
Posts: 3
After much gnashing of teeth...

My problem seems to be fixed by using Session.saveOrUpdateCopy(), AND doing a manual flush before commiting.

If I leave the session to automatically flush, the child objects are not properly persisted. (This problem only occurs when the object is manipulated after the session that found the object had been closed).

So the fixed code is something along the lines of:

Session s1 = HibernateUtil.getSession()
MyObject x = findObject(s1); // some query using s1
s1.close();

// manipulate x outside of a Session
x.setValue("new value");
x.addChild( new MyChild("child1") ); // add a child to x

Session s2 = HibernateUtil.getSession(); // s2 != s1
Transaction t = s2.getTransaction();
s2.saveOrUpdateCopy(x);
s2.flush(); // --- this is the key thing ----
t.commit();
s2.close();


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 4 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.