Hibernate Books

All times are UTC - 5 hours [ DST ]



Post new topic Reply to topic  [ 8 posts ] 
Author Message
 Post subject: Problem with all-delete-orphan (in an update operation)
PostPosted: Tue Jan 04, 2005 10:05 am 
Newbie

Joined: Tue Jan 04, 2005 9:22 am
Posts: 8
Dears,

I have a parent with two children objects in database. I try to update the parent and its children via creating new parent (with same id) and adding a new children to this parent. I expect that all old children should be removed when I persist this new parent object. But, those two children are remained unchanged!!
Sorry for long log trace, i hope this help you to detect the problem.

Thanks for your attention,
Masoud.


Hibernate version: Hibernate 2.1.6

Mapping documents:
Code:
<class name="Post" table="T04_POSTS">
...
   <set
   name="postalBags"
   cascade="all-delete-orphan"
   inverse="true">
   <key column="POST_ID"/>
   <one-to-many class="PostalBag"/>
   </set>
...
</class>

<class name="PostalBag" table="T04_POSTAL_BAGS">
...
   <many-to-one name="post" column="POST_ID" not-null="true"/>
...
</class>

Code between sessionFactory.openSession() and session.close():
Code:
   Post post = new Post();
   post.setId(new Long(1));
   post.setName("Post-11112");         
   PostalBag pb2 = new PostalBag("bag-44");
   post.addPostalBag(pb2);
   session.saveOrUpdate(post);

Full stack trace of any exception that occurs:no exception

Name and version of the database you are using:Oracle 10g

The generated SQL (show_sql=true):
Hibernate: select S04_PostalBag_Sequence.nextval from dual
Hibernate: insert into T04_POSTAL_BAGS (POST_ID, name, created, id) values (?, ?, ?, ?)
Hibernate: update T04_POSTS set name=? where id=?

Debug level Hibernate log excerpt:



[java] DEBUG [main] (JDBCTransaction.java:41) - current autocommit status:false
[java] DEBUG [main] (Cascades.java:341) - id unsaved-value strategy NULL
[java] DEBUG [main] (SessionImpl.java:1392) - saveOrUpdate() previously saved instance with id: 1
[java] DEBUG [main] (SessionImpl.java:1440) - updating [net.sf.hiber.four.domain.Post#1]
[java] DEBUG [main] (SessionImpl.java:1287) - collection dereferenced while transient [net.sf.hiber.four.domain.Post.postalBags#1]
[java] DEBUG [main] (Cascades.java:497) - processing cascades for: net.sf.hiber.four.domain.Post
[java] DEBUG [main] (Cascades.java:524) - cascading to collection: net.sf.hiber.four.domain.Post.postalBags
[java] DEBUG [main] (Cascades.java:113) - cascading to saveOrUpdate()
[java] DEBUG [main] (SessionImpl.java:1387) - saveOrUpdate() unsaved instance
[java] DEBUG [main] (BatcherImpl.java:200) - about to open: 0 open PreparedStatements, 0 open ResultSets
[java] DEBUG [main] (BatcherImpl.java:226) - select S04_PostalBag_Sequence.nextval from dual
[java] Hibernate: select S04_PostalBag_Sequence.nextval from dual
[java] DEBUG [main] (BatcherImpl.java:249) - preparing statement
[java] DEBUG [main] (SequenceGenerator.java:81) - Sequence identifier generated: 5
[java] DEBUG [main] (BatcherImpl.java:207) - done closing: 0 open PreparedStatements, 0 open ResultSets
[java] DEBUG [main] (BatcherImpl.java:269) - closing statement
[java] DEBUG [main] (SessionImpl.java:778) - generated identifier: 5
[java] DEBUG [main] (SessionImpl.java:825) - saving [net.sf.hiber.four.domain.PostalBag#5]
[java] DEBUG [main] (Cascades.java:497) - processing cascades for: net.sf.hiber.four.domain.PostalBag
[java] DEBUG [main] (Cascades.java:113) - cascading to saveOrUpdate()
[java] DEBUG [main] (SessionImpl.java:1372) - saveOrUpdate() persistent instance
[java] DEBUG [main] (Cascades.java:506) - done processing cascades for: net.sf.hiber.four.domain.PostalBag
[java] DEBUG [main] (Cascades.java:497) - processing cascades for: net.sf.hiber.four.domain.PostalBag
[java] DEBUG [main] (Cascades.java:506) - done processing cascades for: net.sf.hiber.four.domain.PostalBag
[java] DEBUG [main] (Cascades.java:506) - done processing cascades for: net.sf.hiber.four.domain.Post
[java] DEBUG [main] (JDBCTransaction.java:59) - commit
[java] DEBUG [main] (SessionImpl.java:2246) - flushing session
[java] DEBUG [main] (Cascades.java:497) - processing cascades for: net.sf.hiber.four.domain.Post
[java] DEBUG [main] (Cascades.java:524) - cascading to collection: net.sf.hiber.four.domain.Post.postalBags
[java] DEBUG [main] (Cascades.java:113) - cascading to saveOrUpdate()
[java] DEBUG [main] (SessionImpl.java:1372) - saveOrUpdate() persistent instance
[java] DEBUG [main] (Cascades.java:506) - done processing cascades for: net.sf.hiber.four.domain.Post
[java] DEBUG [main] (Cascades.java:497) - processing cascades for: net.sf.hiber.four.domain.PostalBag
[java] DEBUG [main] (Cascades.java:113) - cascading to saveOrUpdate()
[java] DEBUG [main] (SessionImpl.java:1372) - saveOrUpdate() persistent instance
[java] DEBUG [main] (Cascades.java:506) - done processing cascades for: net.sf.hiber.four.domain.PostalBag
[java] DEBUG [main] (SessionImpl.java:2439) - Flushing entities and processing referenced collections
[java] DEBUG [main] (WrapVisitor.java:81) - Wrapped collection in role: net.sf.hiber.four.domain.Post.postalBags
[java] DEBUG [main] (SessionImpl.java:2533) - Updating entity: [net.sf.hiber.four.domain.Post#1]
[java] DEBUG [main] (SessionImpl.java:2884) - Collection found: [net.sf.hiber.four.domain.Post.postalBags#1], was: [<unreferenced>]
[java] DEBUG [main] (SessionImpl.java:2780) - Processing unreferenced collections
[java] DEBUG [main] (SessionImpl.java:2794) - Scheduling collection removes/(re)creates/updates
[java] DEBUG [main] (SessionImpl.java:2270) - Flushed: 1 insertions, 1 updates, 0 deletions to 2 objects
[java] DEBUG [main] (SessionImpl.java:2275) - Flushed: 1 (re)creations, 0 updates, 1 removals to 1 collections
[java] DEBUG [main] (Printer.java:75) - listing entities:
[java] DEBUG [main] (Printer.java:82) - net.sf.hiber.four.domain.PostalBag{created=null, name=bag-44, post=Post#1, id=5}
[java] DEBUG [main] (Printer.java:82) - net.sf.hiber.four.domain.Post{created=null, postalBags=[PostalBag#5], name=Post-11112, id=1}
[java] DEBUG [main] (SessionImpl.java:2359) - executing flush
[java] DEBUG [main] (EntityPersister.java:453) - Inserting entity: [net.sf.hiber.four.domain.PostalBag#5]
[java] DEBUG [main] (BatcherImpl.java:200) - about to open: 0 open PreparedStatements, 0 open ResultSets
[java] DEBUG [main] (BatcherImpl.java:226) - insert into T04_POSTAL_BAGS (POST_ID, name, created, id) values (?, ?, ?, ?)
[java] Hibernate: insert into T04_POSTAL_BAGS (POST_ID, name, created, id) values (?, ?, ?, ?)
[java] DEBUG [main] (BatcherImpl.java:249) - preparing statement
[java] DEBUG [main] (EntityPersister.java:388) - Dehydrating entity: [net.sf.hiber.four.domain.PostalBag#5]
[java] DEBUG [main] (NullableType.java:46) - binding '1' to parameter: 1
[java] DEBUG [main] (NullableType.java:46) - binding 'bag-44' to parameter: 2
[java] DEBUG [main] (NullableType.java:41) - binding null to parameter: 3
[java] DEBUG [main] (NullableType.java:46) - binding '5' to parameter: 4
[java] DEBUG [main] (BatchingBatcher.java:28) - Adding to batch
[java] DEBUG [main] (BatchingBatcher.java:50) - Executing batch size: 1
[java] DEBUG [main] (BatchingBatcher.java:58) - success of batch update unknown: 0
[java] DEBUG [main] (BatcherImpl.java:207) - done closing: 0 open PreparedStatements, 0 open ResultSets
[java] DEBUG [main] (BatcherImpl.java:269) - closing statement
[java] DEBUG [main] (EntityPersister.java:648) - Updating entity: [net.sf.hiber.four.domain.Post#1]
[java] DEBUG [main] (BatcherImpl.java:200) - about to open: 0 open PreparedStatements, 0 open ResultSets
[java] DEBUG [main] (BatcherImpl.java:226) - update T04_POSTS set name=? where id=?
[java] Hibernate: update T04_POSTS set name=? where id=?
[java] DEBUG [main] (BatcherImpl.java:249) - preparing statement
[java] DEBUG [main] (EntityPersister.java:388) - Dehydrating entity: [net.sf.hiber.four.domain.Post#1]
[java] DEBUG [main] (NullableType.java:46) - binding 'Post-11112' to parameter: 1
[java] DEBUG [main] (NullableType.java:46) - binding '1' to parameter: 2
[java] DEBUG [main] (BatchingBatcher.java:28) - Adding to batch
[java] DEBUG [main] (BatchingBatcher.java:50) - Executing batch size: 1


Top
 Profile  
 
 Post subject: Some related codes!
PostPosted: Tue Jan 04, 2005 10:39 am 
Newbie

Joined: Tue Jan 04, 2005 9:22 am
Posts: 8
This is the adding child method:

Code:
public class Post{
    private Set postalBags;
...
   public void addPostalBag(PostalBag bag){
      if(postalBags == null)
         postalBags = new HashSet();
      postalBags.add(bag);
      bag.setPost(this);
   }
...
}



This is the child class:
Code:
public class PostalBag {
     private Post post;
  ...
}


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jan 04, 2005 10:42 am 
Hibernate Team
Hibernate Team

Joined: Tue Sep 09, 2003 2:10 pm
Posts: 3246
Location: Passau, Germany
all-delete-orphan does not work like this, it only works if you remove stuff from a collection originally loaded by hibernate.


Top
 Profile  
 
 Post subject: Database initializations
PostPosted: Tue Jan 04, 2005 10:50 am 
Newbie

Joined: Tue Jan 04, 2005 9:22 am
Posts: 8
This segment is already executed! So, we have a parent and two child in database.
Code:
   Post post = new Post();
   post.setName("Post-111");
   
   post.addPostalBag(new PostalBag("bag-1"));
   post.addPostalBag(new PostalBag("bag-2"));
   session.saveOrUpdate(post);


This is some records-dump from database:

Code:
Before update:

T04_PoSTS                       T04_POSTALBAGS
=========                       ===============
ID   Name                       ID   POST_ID   NAME
---------------                 -------------------
1    Post-111                   1     1        bag-2
                                2     1        bag-1


After update:

T04_PoSTS                       T04_POSTALBAGS
=========                       ===============
ID   Name                       ID   POST_ID   NAME
---------------                 -------------------
1    Post-11112                 1     1        bag-2
                                2     1        bag-1
                                3     1        bag-44


Top
 Profile  
 
 Post subject: Am I right?
PostPosted: Tue Jan 04, 2005 11:04 am 
Newbie

Joined: Tue Jan 04, 2005 9:22 am
Posts: 8
So, the only solution for such a this parent child update is the following steps:

- fetch the parent (that contains its children as well)
- for all old children do
----- remove the child from parent's collection
----- nullifying the parent attibute
- adding all new children to parent's collection
- update parent with new value-properties as well


Top
 Profile  
 
 Post subject: Is this another solution recommended?
PostPosted: Tue Jan 04, 2005 11:31 am 
Newbie

Joined: Tue Jan 04, 2005 9:22 am
Posts: 8
You know, I am using hibernate in a web application. The following steps are performing:

- In the a search action, the parent object is fetched.
- Related html content is generated (including IDs).
- data content is changed by user (in browser) and is post to server
- a new fresh parent object is created and is filled.
- up-to-date parent object is stored in database.

So, it seems due performance issues, we can merge two classes, and use a composite-element for the child.

Code:
<class name="Post14" table="T14_POSTS">
    <set name="postalBags"  cascade="all"
   inverse="false" table="T14_POSTAL_BAG">
   <key column="POST_ID" />
   <composite-element class="PostalBag14">
      ...
       <property name="name"/>
     </composite-element>         
        </set>
...
</class>


Top
 Profile  
 
 Post subject: Great Web Architecture
PostPosted: Tue Jan 04, 2005 5:01 pm 
Newbie

Joined: Tue Jan 04, 2005 4:55 pm
Posts: 1
Masoud,

I was just wonder how to use hibernate in our web application projects, what you told here, showed me the way.

Thanks alot.

Farzad.


Top
 Profile  
 
 Post subject: Using List collection updating a detached parent/child
PostPosted: Thu Apr 10, 2008 1:47 pm 
Newbie

Joined: Thu Apr 10, 2008 12:58 pm
Posts: 1
I have a parent/child relationship where a parent has to have an ordered collection of children. I read around trying to do this using a list but never got the delete-orphan to work when the parent and children are detached. So here is my scenario (typical web app):
User makes a search, I retrive the parent and collection convert it to UI object and send out the response. The session is closed. The user modifies the children (add new or remove existing or update existing) and saves the parent.
Here is my class and mapping:

Code:
public class Parent {
  private Long parentId;
  private List children = new ArrayList();
  private String name;

   /**add property getters & setters **/

  public void addChild(Child c){
    this.children.add(c);
  }
  public void addChildren(List childrenList){
    this.children.addAll(childrenList);
  }
 

}

mapping parent.hbm.xml
<hibernate-mapping >
  <class name="Parent" table="PARENT">
    <id name="parentId" column="P_ID">
      <generator class="native"/>
    </id>
    <property name="name" column="P_NM" not-null="true"  />

    <list name="children"  lazy="false" cascade="all, delete-orphan" >
        <key column="P_ID" not-null="true" />
        <list-index column="SORTING_INDX" />
        <one-to-many class="Child"/>
    </list>       
  </class>
</hibernate-mapping>

public class Child {
  private Parent parent;
  private Long childId;
  private Date myDate;
/** getters and setters **/
}

mapping child.hbm.xml
<hibernate-mapping>
  <class name="Child" table="CHILD">
    <id name="childId" column="C_ID">
      <generator class="native"/>
    </id>
    <property name="myDate" column="C_DT" />
    <many-to-one name="parent" class="Parent" column="P_ID" not-null="true" insert="false" update="false" />

  </class>
</hibernate-mapping>

My DAO save/update method:

public Parent saveParent(Parent p) {
  if(p.getParentId()==null)
   getHibernateTemplate().save(p);
  else
   getHibernateTemplate().merge(p);
  return p;
}

Test it
public ResultUI findParent(SearchCriteria criteria){
     //create my detachedCriteria from my business criteria object   
     //find the parent using detachedcriteria
     //convert result to UI object and return
}

/** called from web Layer
      You can add child / remove child or update a child in the ui List
      Remember - existing child should have childId and new child will
      have a null id - for hibernate to do appropriate query
**/
public ResultUI saveParent(ParentUI pUI) {
     //convert UI object to my parent
     Parent p = new Parent();
     p.setParentId(pUI.getParentId());
     p.setName(pUI.getName());
   
    List children = new ArrayList();
    //create children
   
    //for each child in UI
        Child c = new Child();
        c.setParent(p);
        //TODO: get other properties from UI
        //add child to list
        children.add(c);
   //finally ADD the children ( NOT setChildren )
   p.addChildren(children);
   myDao.saveParent(p);
}



The above code will :
1. insert new child if you added any
2. remove any child from table that you removed from list --- key point to not is we have used a merge() instead of an update() in our dao. so hibernate will merge this object with the one already in session and the delete-orphan will cause a delete query.
3. updates a child if you updated a child

Finally we got this to work like a charm.

Good Luck All.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 8 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.