-->
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: NHibernate Tries to Update Children Despite "cascade=no
PostPosted: Thu Jul 10, 2008 4:49 am 
Beginner
Beginner

Joined: Thu Dec 01, 2005 1:09 pm
Posts: 33
Problem description:

In my parent class, I have a list of child objects which I want NHibernate to load when I load the parent.
However, I never want NHibernate update the children when I save the parent, I'll do that myself.

Unfortunately however, NHibernate does try to delete the reference to the parent when I save a parent that doesn't reference any children.
This causes and exception to be thrown as the parent reference is a non-null column in my database.

How can this be solved?


NHibernate version:

1.0.3.0

Mapping documents:

Code:
<class name="Parent" table="PARENT">
    <id name="ID" column="PARENT_ID" type="Int32" unsaved-value="-1">
        <generator class="MyGenerator" />
    </id>

    <property name="Foo" column="FOO" type="DateTime" />

    <bag name="Children" cascade="none">
        <key column="PARENT_ID"/>
        <one-to-many class="Child"/>
    </bag>
</class>

<class name="Child" table="CHILD">
    <id name="ID" column="CHILD_ID" type="Int32" unsaved-value="-1">
        <generator class="MyGenerator" />
    </id>

    <property name="Bar" column="BAR" type="Int32" />

    <many-to-one name="Parent"
        column="PARENT_ID"
        class="Parent"
        cascade="none" />
</class>


Code between sessionFactory.openSession() and session.close():

Roughly something like this:

Code:
public void SaveParentAndChildren( Parent p, IList<Child> children )
{
    Debug.Assert( p.ID == -1 );
    Debug.Assert( p.Children == null );

    // open session and transaction (stripped)

    // save the parent
    session.Save( p );

    // save the children
    foreach ( Child c in children )
    {
        Debug.Assert( c.ID == -1 );
        Debug.Assert( c.Parent == p );
        session.Save( c );
    }

    // commit transaction, close session (stripped)
}

public void UpdateSavedParentOnly( Parent p )
{
    Debug.Assert( p.ID > 0 );
    Debug.Assert( p.Children == null );

    // open session and transaction

    // update the parent
    p.Foo = DateTime.Now;
    session.Update( p );

    // commit transaction, close session (stripped)
    // --> upon committing the transaction, an exception is raised
    //     because NHibernate tries to update the children as well
}

public void Foobar( )
{
    Parent p = new Parent( );

    List<Child> children = new List<Child>( );
    for ( int i = 0; i < 3; i++ )
        children.Add( new Child( ) );

    SaveParentAndChildren( p, children ); // works ok
    UpdateSavedParentOnly( p ); // throws an exception
}


Full stack trace of any exception that occurs:

Quote:
NHibernate.ADOException : could not delete collection: [Parent.Children#3]
at NHibernate.Collection.AbstractCollectionPersister.Remove(Object id, ISessionImplementor session)
at NHibernate.Impl.ScheduledCollectionRemove.Execute()
at NHibernate.Impl.SessionImpl.Execute(IExecutable executable)
at NHibernate.Impl.SessionImpl.ExecuteAll(IList list)
at NHibernate.Impl.SessionImpl.Execute()
at NHibernate.Impl.SessionImpl.Flush()
at NHibernate.Transaction.AdoTransaction.Commit()


Name and version of the database you are using:

Gupta SQLBase 9.0.1

The generated SQL (show_sql=true):

Code:
UPDATE CHILD SET PARENT_ID = NULL WHERE PARENT_ID = :1


As PARENT_ID is a non-null column, this leads to the above the exception.


Top
 Profile  
 
 Post subject: Re: NHibernate Tries to Update Children Despite "cascad
PostPosted: Thu Jul 10, 2008 6:56 pm 
Newbie

Joined: Sat Dec 25, 2004 5:04 am
Posts: 1
Location: Berlin, Germany
GrønnDemon wrote:
Problem description:

In my parent class, I have a list of child objects which I want NHibernate to load when I load the parent.
However, I never want NHibernate update the children when I save the parent, I'll do that myself.

Quote:
NHibernate.ADOException : could not delete collection: The generated SQL (show_sql=true):

Code:
UPDATE CHILD SET PARENT_ID = NULL WHERE PARENT_ID = :1


As PARENT_ID is a non-null column, this leads to the above the exception.



Hi Demon,

First of all, I suspect bag is not the type of collection that matches a parent child relationship (taking into account that Hibernate does not preserve order even though a bag maps to a list). I'd suggest a set instead.

Then I'd propose adding the inverse="true" to the set within the parent, as the primary - mutable - origin is at the child side (you only want a convenient - reverse - view of all children that is managed within the child itself). See Hibernate Forums - View topic - inverse=true for an informal discussion of inverse="true".

Thus the mappings should look similar to:
Code:
<class name="Parent" table="PARENT">
    <id name="ID" column="PARENT_ID" type="Int32" unsaved-value="-1">
        <generator class="MyGenerator" />
    </id>

    <property name="Foo" column="FOO" type="DateTime" />

    <set name="Children" cascade="none" inverse="true">
        <key column="PARENT_ID"/>
        <one-to-many class="Child"/>
    </set>
</class>

<class name="Child" table="CHILD">
    <id name="ID" column="CHILD_ID" type="Int32" unsaved-value="-1">
        <generator class="MyGenerator" />
    </id>

    <property name="Bar" column="BAR" type="Int32" />

    <many-to-one name="Parent"
        column="PARENT_ID"
        class="Parent"
        cascade="none" />
</class>


Good luck,
Reiner

Disclaimer: I'm not a Hibernate guru at all...


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jul 11, 2008 3:24 am 
Beginner
Beginner

Joined: Thu Dec 01, 2005 1:09 pm
Posts: 33
Thanks a lot, Reiner! This solved the problem. :)
Looks like you're a Hibernate Guru after all. ;)


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.