-->
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.  [ 1 post ] 
Author Message
 Post subject: saveOrUpdate and delete-orphan for 1:M
PostPosted: Mon Jan 04, 2010 11:14 am 
Newbie

Joined: Wed Nov 05, 2008 1:17 pm
Posts: 7
I have a unidirectional 1:M Parent-Child relationship mapped as entities with "all,delete-orphan" set as the cascade style. I am using Spring's HibernateTemplate for testing. I have a unit test that simulates sending a Parent with a set of Child objects to a Flex client and removes one of the children from the set prior to sending it back to the service layer. The problem I'm seeing is that using hibernateTemplate.saveOrUpdate(parent) doesn't actually remove the child entity but instead marks the child entity's foreign key to the parent as null. If I use merge() instead, the behavior is as expected in that the child entity is deleted as well.

I'd like to map this as a component, but the child properties can be null.

Code:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.tim" default-access="field" >
   <class name="Parent"
      table="PARENT"
       >
      <id name="id" type="java.lang.Long">
         <column name="PARENT_ID" precision="10" scale="0" />
         <generator class="native">
         </generator>
      </id>

        <property name="name" type="java.lang.String">
           <column name="NAME" length="255" not-null="true" />
        </property>
      
      <set name="children"
           cascade="all,delete-orphan">

           <key column="PARENT_ID" />
           <one-to-many class="Child" />
      </set>
   </class>
   
   <class name="Child"
          table="CHILD">
          
      <id name="id" type="java.lang.Long">
         <column name="CHILD_ID" precision="10" scale="0" />
         <generator class="native">
         </generator>
      </id>

        <property name="name" type="string">
           <column name="CHILD_NAME" length="255" not-null="true" />
        </property>
       
   </class>
</hibernate-mapping>

Test case:
  public void onSetUp() throws Exception
   {
      // clean the data
      jdbcTemplate.execute( "delete from CHILD" );
      jdbcTemplate.execute( "delete from PARENT" );

      // stage the data
      jdbcTemplate
                  .execute( "insert into PARENT (PARENT_ID,NAME) values "
                            + "(500,'parent1')" );
      jdbcTemplate
                  .execute( "insert into PARENT (PARENT_ID,NAME) values "
                            + "(510,'parent2')" );

      jdbcTemplate.execute( "insert into CHILD (CHILD_ID, PARENT_ID, CHILD_NAME) values "
                            + "(300,500,'child1')" );
      jdbcTemplate.execute( "insert into CHILD (CHILD_ID, PARENT_ID, CHILD_NAME) values "
                            + "(310,500,'child2')" );
      jdbcTemplate.execute( "insert into CHILD (CHILD_ID, PARENT_ID, CHILD_NAME) values "
                            + "(320,510,'child3')" );
       
      setComplete();
      startNewTransaction();
   }
   @NotTransactional
   public void testRemoveChildFromDetached() throws Exception
   {
      final Parent parent = new Parent(  );
      parent.setId( Long.valueOf( "500" ) );
      parent.setName( "parent1_modified" );
     
      final Child child1 = new Child();
      child1.setName( "child1_modified" );
      child1.setId( Long.valueOf( "310") );
      final Set<Child> children = new LinkedHashSet<Child>();
      children.add( child1 );
      parent.setChildren( children );
     
      System.out.println( "******* saveOrUpdate() of parent: " + parent + " *******" );
      // NOTE: uncomment the following for the test to pass
//      hibernateTemplate.merge( parent );
      // NOTE: this line will not result in the child deletion
      hibernateTemplate.saveOrUpdate( parent );
   
      endTransaction();
      startNewTransaction();
      System.out.println( "******* loading parent again *********" );
      final Parent parentCheck = (Parent)hibernateTemplate.get( Parent.class, Long.valueOf( 500 ) );
      assertTrue( parentCheck.getChildren().size() == 1);

      final long rowCount =
         jdbcTemplate.queryForLong( "select count(*) from CHILD where CHILD_ID='300'" );
      assertEquals( "Count of rows in CHILD should be 0 for CHILD_ID='300'", 0, rowCount );
   }



If I execute this test with saveOrUpdate() uncommented, I'll end up with all three child rows (300, 310, 320), but 310 will have a PARENT_ID of null. If I use merge() instead, 310 is deleted and the test passes. Is there a good explanation for this?

Thanks for the help.


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

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.