-->
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.  [ 5 posts ] 
Author Message
 Post subject: Deep Clone Object: Curious behavior! Code mistake or Bug?
PostPosted: Wed Jun 14, 2006 2:11 pm 
Newbie

Joined: Tue Jun 06, 2006 7:33 pm
Posts: 11
Hi,
I need to use deep clone object...but some Hibernate operation having an strange behavior: the saveOrUpdate method.

I load an object from the database, and I clone it. I modify the clone and save it into the database.

the behavior is different when I change the value on a child objet (work great) and I delete the child.
Deleting the child isn't impact into the data base!!!

if I use the merge operation change and delete are impact to the database.
if I use the saveOrUpdate operation only the change is impact!

For more clarity I make a JUnit Test Case:

Code:
package test.clone;

import java.util.ArrayList;
import java.util.Iterator;

import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import org.springframework.core.io.ClassPathResource;
import junit.framework.TestCase;

public class ParentTest extends TestCase {
   
   private Parent parent;
   private Child child_1;
   private Child child_2;
   
   private ClassPathXmlApplicationContext ctx;
   private DAO dao;

   protected void setUp() throws Exception {
      super.setUp();
      parent = new Parent("parent_field_1", "parent_field_2");
      child_1 = new Child("child_field_1", "child_field_2");
      child_2 = new Child("child_field_1", "child_field_2");
      ctx =  new ClassPathXmlApplicationContext("applicationContext.xml");
        dao =  (DAO) ctx.getBean("DAO");
   }

   protected void tearDown() throws Exception {
      super.tearDown();
   }

   public void testClone() {
      System.out.println("\n \n TEST CASE testClone :");
      parent.addChildren(child_1);
      parent.addChildren(child_2);
      
      Parent pclone = (Parent) parent.clone();
      // change only Clone children's
      for (Iterator iter = pclone.getChildren().iterator(); iter.hasNext();) {
         Child element = (Child) iter.next();
         element.setChild_field_1("CLONE_child_field_1");
         element.setChild_field_2("CLONE_child_field_2");         
      }
      
      System.out.println("ORIGINAL: "+parent);
      System.out.println("CLONE   : "+pclone);
      
      // ORIGINAL
      for (Iterator iter = parent.getChildren().iterator(); iter.hasNext();) {
         Child element = (Child) iter.next();
         assertEquals("child_field_1",element.getChild_field_1());
         assertEquals("child_field_2",element.getChild_field_2());
      }
      
      // CLONE MODIFICATION
      for (Iterator iter = pclone.getChildren().iterator(); iter.hasNext();) {
         Child element = (Child) iter.next();
         assertEquals("CLONE_child_field_1",element.getChild_field_1());
         assertEquals("CLONE_child_field_2",element.getChild_field_2());
      }
   }
   
   public void testUpdateCloneChildren_AND_SAVE_INTO_DATABASE() {
      System.out.println("\n \n TEST CASE testUpdateCloneChildren_AND_SAVE_INTO_DATABASE :");
      // save the original object into database
      parent.addChildren(child_1);
      parent = dao.merge(parent);
      
      // find the original objet from the database
      Parent parentDataBase = dao.findById(parent.getId());
      
      // clone the original objet from the database
      Parent pclone = (Parent) parentDataBase.clone();
      
      // only change Clone children's
      for (Iterator iter = pclone.getChildren().iterator(); iter.hasNext();) {
         Child element = (Child) iter.next();
         element.setChild_field_1("CLONE_child_field_1");
         element.setChild_field_2("CLONE_child_field_2");         
      }
      
      // update the clone object into database
      Parent parentCloneDataBase = dao.merge(pclone);
      assertEquals(parent.getId(), parentCloneDataBase.getId());
      
      // check the correct update from the database
      parentCloneDataBase = dao.findById(parent.getId());
      assertEquals(parent.getId(), parentCloneDataBase.getId());
      
      for (Iterator iter = parentCloneDataBase.getChildren().iterator(); iter.hasNext();) {
         Child element = (Child) iter.next();
         assertEquals("CLONE_child_field_1",element.getChild_field_1());
         assertEquals("CLONE_child_field_2",element.getChild_field_2());
      }
      
      System.out.println("ORIGINAL NOT UPDATED   : "+parent);
      System.out.println("CLONE UPDATED DATABASE : "+parentCloneDataBase);      
   }

   public void testDeleteCloneChildren_AND_MERGE_INTO_DATABASE() {
      System.out.println("\n \n testDeleteCloneChildren_AND_MERGE_INTO_DATABASE :");
      parent.addChildren(child_1);      
      
      // save the original object into database
      parent = dao.merge(parent);
      
      // find the original objet from the database
      Parent parentDataBase = dao.findById(parent.getId());
      
      // clone the original objet from the database
      Parent pclone = (Parent) parentDataBase.clone();
      
      // only remove Clone children's
       ArrayList al = (ArrayList) pclone.getChildren();
         for (int i = al.size()-1; i >= 0 ; i--) {
            Child onechildclone = (Child) al.get(i);
            pclone.removeChildren(onechildclone);
         }
      
      // update the clone object into database
      Parent parentCloneDataBase = dao.merge(pclone);
      assertEquals(parent.getId(), parentCloneDataBase.getId());
      
      // check the correct delete from the database
      parentCloneDataBase = dao.findById(parent.getId());
      
      System.out.println("ORIGINAL NOT UPDATED   : "+parent);
      System.out.println("CLONE DELETED CHILDREN : "+pclone);
      System.out.println("CLONE DELETED CHILDREN RETURN DROM DATABASE : "+parentCloneDataBase);
      
      assertEquals(1, parent.getChildren().size());
      assertEquals(0, pclone.getChildren().size());
      assertEquals(0, parentCloneDataBase.getChildren().size());      
   }
   
   public void testDeleteCloneChildren_AND_SAVE_INTO_DATABASE() {
      System.out.println("\n \n testDeleteCloneChildren_AND_SAVE_INTO_DATABASE :");
      parent.addChildren(child_1);      
      
      // save the original object into database
      parent = dao.save(parent);
      
      // find the original objet from the database
      Parent parentDataBase = dao.findById(parent.getId());
      
      // clone the original objet from the database
      Parent pclone = (Parent) parentDataBase.clone();
      
      // only remove Clone children's
       ArrayList al = (ArrayList) pclone.getChildren();
         for (int i = al.size()-1; i >= 0 ; i--) {
            Child onechildclone = (Child) al.get(i);
            pclone.removeChildren(onechildclone);
         }
      
      // update the clone object into database
      Parent parentCloneDataBase = dao.save(pclone);
      assertEquals(parent.getId(), parentCloneDataBase.getId());
      
      // check the correct delete from the database
      parentCloneDataBase = dao.findById(parent.getId());
      
      System.out.println("ORIGINAL NOT UPDATED   : "+parent);
      System.out.println("CLONE DELETED CHILDREN : "+pclone);
      System.out.println("CLONE DELETED CHILDREN RETURN DROM DATABASE : "+parentCloneDataBase);
      
      assertEquals(1, parent.getChildren().size());
      assertEquals(0, pclone.getChildren().size());
      assertEquals(0, parentCloneDataBase.getChildren().size());      
   }
   
}


Why the testDeleteCloneChildren_AND_SAVE_INTO_DATABASE case doesn't delete the child element:
Parent [ | id: 1 | Parent_field_1: parent_field_1 | Parent_field_2: parent_field_2]
Quote:
--> Child [ | id: 1 | idParent: 1 | Child_field_1: child_field_1 | Child_field_2: child_field_2]


Result Console trace:


testDeleteCloneChildren_AND_SAVE_INTO_DATABASE : WRONG RESULT
Hibernate: insert into PARENT (parent_field_1, parent_field_2) values (?, ?)
Hibernate: insert into CHILD (child_field_1, child_field_2, ID_PARENT) values (?, ?, ?)
Hibernate: select parent0_.ID_PARENT as ID1_0_, parent0_.parent_field_1 as parent2_0_0_, parent0_.parent_field_2 as parent3_0_0_ from PARENT parent0_ where parent0_.ID_PARENT=?
Hibernate: select children0_.ID_PARENT as ID4_1_, children0_.ID_CHILD as ID1_1_, children0_.ID_CHILD as ID1_0_, children0_.child_field_1 as child2_1_0_, children0_.child_field_2 as child3_1_0_, children0_.ID_PARENT as ID4_1_0_ from CHILD children0_ where children0_.ID_PARENT=?
Hibernate: select parent0_.ID_PARENT as ID1_0_, parent0_.parent_field_1 as parent2_0_0_, parent0_.parent_field_2 as parent3_0_0_ from PARENT parent0_ where parent0_.ID_PARENT=?
Hibernate: select children0_.ID_PARENT as ID4_1_, children0_.ID_CHILD as ID1_1_, children0_.ID_CHILD as ID1_0_, children0_.child_field_1 as child2_1_0_, children0_.child_field_2 as child3_1_0_, children0_.ID_PARENT as ID4_1_0_ from CHILD children0_ where children0_.ID_PARENT=?
Hibernate: update PARENT set parent_field_1=?, parent_field_2=? where ID_PARENT=?
Hibernate: select parent0_.ID_PARENT as ID1_0_, parent0_.parent_field_1 as parent2_0_0_, parent0_.parent_field_2 as parent3_0_0_ from PARENT parent0_ where parent0_.ID_PARENT=?
Hibernate: select children0_.ID_PARENT as ID4_1_, children0_.ID_CHILD as ID1_1_, children0_.ID_CHILD as ID1_0_, children0_.child_field_1 as child2_1_0_, children0_.child_field_2 as child3_1_0_, children0_.ID_PARENT as ID4_1_0_ from CHILD children0_ where children0_.ID_PARENT=?
Hibernate: select parent0_.ID_PARENT as ID1_0_, parent0_.parent_field_1 as parent2_0_0_, parent0_.parent_field_2 as parent3_0_0_ from PARENT parent0_ where parent0_.ID_PARENT=?
Hibernate: select children0_.ID_PARENT as ID4_1_, children0_.ID_CHILD as ID1_1_, children0_.ID_CHILD as ID1_0_, children0_.child_field_1 as child2_1_0_, children0_.child_field_2 as child3_1_0_, children0_.ID_PARENT as ID4_1_0_ from CHILD children0_ where children0_.ID_PARENT=?
ORIGINAL NOT UPDATED : Parent [ | id: 1 | Parent_field_1: parent_field_1 | Parent_field_2: parent_field_2]
--> Child [ | id: 1 | idParent: 1 | Child_field_1: child_field_1 | Child_field_2: child_field_2]
CLONE DELETED CHILDREN : Parent [ | id: 1 | Parent_field_1: parent_field_1 | Parent_field_2: parent_field_2]
CLONE DELETED CHILDREN RETURN DROM DATABASE : Parent [ | id: 1 | Parent_field_1: parent_field_1 | Parent_field_2: parent_field_2]
--> Child [ | id: 1 | idParent: 1 | Child_field_1: child_field_1 | Child_field_2: child_field_2]


testDeleteCloneChildren_AND_MERGE_INTO_DATABASE : OK
Hibernate: insert into CHILD (child_field_1, child_field_2, ID_PARENT) values (?, ?, ?)
Hibernate: insert into PARENT (parent_field_1, parent_field_2) values (?, ?)
Hibernate: update CHILD set child_field_1=?, child_field_2=?, ID_PARENT=? where ID_CHILD=?
Hibernate: select parent0_.ID_PARENT as ID1_0_, parent0_.parent_field_1 as parent2_2_0_, parent0_.parent_field_2 as parent3_2_0_ from PARENT parent0_ where parent0_.ID_PARENT=?
Hibernate: select children0_.ID_PARENT as ID4_1_, children0_.ID_CHILD as ID1_1_, children0_.ID_CHILD as ID1_0_, children0_.child_field_1 as child2_3_0_, children0_.child_field_2 as child3_3_0_, children0_.ID_PARENT as ID4_3_0_ from CHILD children0_ where children0_.ID_PARENT=?
Hibernate: select parent0_.ID_PARENT as ID1_0_, parent0_.parent_field_1 as parent2_2_0_, parent0_.parent_field_2 as parent3_2_0_ from PARENT parent0_ where parent0_.ID_PARENT=?
Hibernate: select children0_.ID_PARENT as ID4_1_, children0_.ID_CHILD as ID1_1_, children0_.ID_CHILD as ID1_0_, children0_.child_field_1 as child2_3_0_, children0_.child_field_2 as child3_3_0_, children0_.ID_PARENT as ID4_3_0_ from CHILD children0_ where children0_.ID_PARENT=?
Hibernate: delete from CHILD where ID_CHILD=?
Hibernate: select parent0_.ID_PARENT as ID1_0_, parent0_.parent_field_1 as parent2_2_0_, parent0_.parent_field_2 as parent3_2_0_ from PARENT parent0_ where parent0_.ID_PARENT=?
Hibernate: select children0_.ID_PARENT as ID4_1_, children0_.ID_CHILD as ID1_1_, children0_.ID_CHILD as ID1_0_, children0_.child_field_1 as child2_3_0_, children0_.child_field_2 as child3_3_0_, children0_.ID_PARENT as ID4_3_0_ from CHILD children0_ where children0_.ID_PARENT=?
ORIGINAL NOT UPDATED : Parent [ | id: 1 | Parent_field_1: parent_field_1 | Parent_field_2: parent_field_2]
--> Child [ | id: 1 | idParent: 1 | Child_field_1: child_field_1 | Child_field_2: child_field_2]
CLONE DELETED CHILDREN : Parent [ | id: 1 | Parent_field_1: parent_field_1 | Parent_field_2: parent_field_2]
CLONE DELETED CHILDREN RETURN DROM DATABASE : Parent [ | id: 1 | Parent_field_1: parent_field_1 | Parent_field_2: parent_field_2]


Quote:
Parent.java

Code:
package test.clone;

import java.io.ObjectInputStream.GetField;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class Parent {
   private Integer id;
   private String parent_field_1="";
   private String parent_field_2="";
   private List children = new ArrayList();

   
   public Parent(){
      
   }
   
   public Parent(Parent object){
      id = object.getId();
      parent_field_1 = object.getParent_field_1();
      parent_field_2 = object.getParent_field_2();
      for (Iterator iter = object.getChildren().iterator(); iter.hasNext();) {
         Child original_child = (Child) iter.next();
         Child cloneChild = (Child) original_child.clone();
         this.getChildren().add(cloneChild);         
      }
   }

   
   public Parent(String str_parent_field_1, String str_parent_field_2) {
      parent_field_1 = str_parent_field_1;
      parent_field_2 = str_parent_field_2;
   }

   public void addChildren (Child oneChild){
      if (oneChild == null)
         throw new IllegalArgumentException("Can't add a null child.");
      if (oneChild.getParent() != null && oneChild.getParent().equals(this))
          throw new IllegalArgumentException("child is already in this parent");
      else if (oneChild.getParent() != null){
          // on pourrait ajouter un test sur les conditions de contrats
          oneChild.getParent().removeChildren(oneChild);
      }
      oneChild.setParent(this);
      this.getChildren().add(oneChild);   
    }
   
    public void removeChildren (Child oneChild){
      if (oneChild == null)
         throw new IllegalArgumentException("Can't add a null child.");     
      oneChild.setParent(null);
      this.getChildren().remove(oneChild);
    }
   
   
   public List getChildren() {
      return children;
   }

   public void setChildren(List children) {
      this.children = children;
   }

   public String getParent_field_1() {
      return parent_field_1;
   }

   public void setParent_field_1(String chield_fiel_1) {
      this.parent_field_1 = chield_fiel_1;
   }

   public String getParent_field_2() {
      return parent_field_2;
   }

   public void setParent_field_2(String chiled_field_2) {
      this.parent_field_2 = chiled_field_2;
   }

   public Integer getId() {
      return id;
   }

   public void setId(Integer id) {
      this.id = id;
   }
   
    public Object clone() {
       return new Parent(this);
    }
   
   public String toString() {     
       StringBuffer strb = new StringBuffer();
         strb.append("Parent [");
         strb.append(" | id: "+ getId());
         strb.append(" | Parent_field_1: "+getParent_field_1());
         strb.append(" | Parent_field_2: "+getParent_field_2());
         strb.append("]");
         for (Iterator iter = getChildren().iterator(); iter.hasNext();) {
            Object element = (Object) iter.next();
            strb.append("\n");
            strb.append(" --> "+element);
         
      }   
       return strb.toString();
    }
   
   
   

}


Quote:
Child.java

Code:
package test.clone;

import java.util.Iterator;

public class Child {
   
   private Integer id;
   private String child_field_1="";
   private String child_field_2="";
    private Parent parent;
   
   public Child(){
      
   }
   
   public Child(Child object){
      id = object.getId();
      child_field_1 = object.getChild_field_1();
      child_field_2 = object.getChild_field_2();
      parent = object.getParent();
   }

   
   
   public Child(String str_child_field_1, String str_child_field_2) {
      child_field_1 = str_child_field_1;
      child_field_2 = str_child_field_2;
   }

   public Parent getParent() {
      return parent;
   }

   public void setParent(Parent parent) {
      this.parent = parent;
   }

   public String getChild_field_1() {
      return child_field_1;
   }

   public void setChild_field_1(String child_field_1) {
      this.child_field_1 = child_field_1;
   }

   public String getChild_field_2() {
      return child_field_2;
   }

   public void setChild_field_2(String child_field_2) {
      this.child_field_2 = child_field_2;
   }

   public Integer getId() {
      return id;
   }

   public void setId(Integer id) {
      this.id = id;
   }
   
    public Object clone() {
       return new Child(this);
    }
   
   public String toString() {     
       StringBuffer strb = new StringBuffer();
         strb.append("Child [");
         strb.append(" | id: "+ getId());
         strb.append(" | idParent: "+getParent().getId());
         strb.append(" | Child_field_1: "+getChild_field_1());
         strb.append(" | Child_field_2: "+getChild_field_2());
         strb.append("]");
       return strb.toString();
    }

}


Quote:
DAO.java

Code:
package test.clone;

import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

public class DAO extends HibernateDaoSupport {
   
   
    public Parent save(Parent transientInstance) {
        try {
            getHibernateTemplate().saveOrUpdate(transientInstance);
            return findById(transientInstance.getId());
        } catch (RuntimeException re) {
            throw re;
        }
    }
   
    public Parent merge(Parent transientInstance) {
        try {
            return (Parent) getHibernateTemplate().merge(transientInstance);
        } catch (RuntimeException re) {
            throw re;
        }
    }
   
    public Parent findById(Integer id) {
        try {
           Parent instance = (Parent) getHibernateTemplate().get(Parent.class, id);
            return instance;
        } catch (RuntimeException re) {
            throw re;
        }
    }
   
   
   public void delete(Parent persistentInstance) {
        try {
            getHibernateTemplate().delete(persistentInstance);           
        } catch (RuntimeException re) {
            throw re;
        }
    }

}


Quote:
Mapping Files

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="test.clone">

    <class name="Parent" table="PARENT">
        <id name="id" column="ID_PARENT" type="java.lang.Integer">
            <generator class="native">
             <!-- param name="sequence">S_PFA_MODIFICATION_REF</param-->
             </generator>
        </id> 
        <property name="parent_field_1" column="parent_field_1" type="java.lang.String"  not-null="false" />           
        <property name="parent_field_2" column="parent_field_2" type="java.lang.String"  not-null="false" />
       
        <!-- *** RELATION AVEC L OBJET CHILD *** -->
        <bag name="children" inverse="true" fetch="select" cascade="save-update,persist,merge,delete,all-delete-orphan" lazy="false">
          <key column="ID_PARENT" />
          <one-to-many class="Child" />
       </bag>
       
    </class>
   
</hibernate-mapping>



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="test.clone">

    <class name="Child" table="CHILD">
        <id name="id" column="ID_CHILD" type="java.lang.Integer">
            <generator class="native">
             <!-- param name="sequence">S_PFA_MODIFICATION_REF</param-->
             </generator>
        </id>
        <property name="child_field_1" column="child_field_1" type="java.lang.String"  not-null="false" />           
        <property name="child_field_2" column="child_field_2" type="java.lang.String"  not-null="false" />
   
        <!-- *** RELATION AVEC L OBJET PARENT *** -->
        <many-to-one column="ID_PARENT" name="parent" class="Parent" />                   
    </class>
   
</hibernate-mapping>


Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>   
   <!-- ========================= Start of PERSISTENCE DEFINITIONS ========================= --> 
    

<bean id="mySQLDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://127.0.0.1:3306/clone"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>

<!-- bean id="oracleDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
      <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
      <property name="url" value="jdbc:oracle:thin:@127.0.0.1:1521:PFA"/>
      <property name="username" value="pf_test"/>
      <property name="password" value="pf_test"/>
</bean-->   

  <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="dataSource" ref="mySQLDataSource"/>
    <property name="mappingResources">
      <list>
            <value>test/clone/Parent.hbm.xml</value>
            <value>test/clone/Child.hbm.xml</value>         
         </list>
    </property>
    <property name="hibernateProperties">
      <props>
        <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
        <prop key="hibernate.show_sql">true</prop>
        <prop key="hibernate.format_sql">true</prop>
         <prop key="hibernate.hbm2ddl.auto">create</prop>       
      </props>
    </property>
    <!-- property name="hibernateProperties">
      <props>
        <prop key="hibernate.dialect">org.hibernate.dialect.OracleDialect</prop>
        <prop key="hibernate.show_sql">true</prop>
        <prop key="hibernate.format_sql">true</prop>
         <prop key="hibernate.hbm2ddl.auto">create</prop>       
      </props>
    </property-->
  </bean>
   
   
   <!-- DAO object: Hibernate implementation -->
   <bean id="DAO" class="test.clone.DAO">
      <property name="sessionFactory"><ref local="sessionFactory"/></property>
   </bean>      
   

   <!-- Add more services here -->
   
</beans>


My configuration:
JUnit
Spring
Hibernate 3.1
Oracle or MySQL data base


Thank Stef


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jun 14, 2006 6:25 pm 
Expert
Expert

Joined: Thu Dec 23, 2004 9:08 pm
Posts: 2008
I see that your clone methods have the two mistakes:
  1. The cloned objects get the same database id as the original object, so when you save it, the original (should) get updated; when you delete it, you (should) get an exception, because the original is still in hibernate's session cache.
  2. Your clone uses new Parent()/new Child(), rather than super.clone(). This is Very Bad News. clone() methods must not do this: if they do, they are breaking the clone() contract. If you want to use the copy constructor approach, create a copy() method or something, don't use clone().


There are any number of reasons that deleting a child object isn't doing anyting, though I would have thought that in most cases, an exception would be thrown, rather than simply nothing happening. However, I wouldn't spend any effort trying to figure out which problem is affecting you. Instead, change your practice to follow java standards: there is a good chance that this will automatically fix things, and if it doesn't, then at least you're starting from the same place as other people who've already solved your problems, so our solutions will apply to your code.

_________________
Code tags are your friend. Know them and use them.


Top
 Profile  
 
 Post subject: Java standards?
PostPosted: Thu Jun 15, 2006 4:18 am 
Newbie

Joined: Tue Jun 06, 2006 7:33 pm
Posts: 11
Hi,
Thanks a lot for the reply I would spend more time to resolve the problem.
In few word could you explain the real difference beetwen the clone and the copy.
Could you tell me some tips to change my practice to follow java standards?

Thanks


Stef


Top
 Profile  
 
 Post subject: I change the code to folow Java standard (I hope...)
PostPosted: Thu Jun 15, 2006 8:07 am 
Newbie

Joined: Tue Jun 06, 2006 7:33 pm
Posts: 11
I change my code but now I receive a classCastException when I retrieve the Objet from Hibernate because I map the ArrayList with a Hibernate Bag

Quote:
p.children = (ArrayList)((ArrayList)children).clone();



Quote:
Parent.java


Code:
package test.clone;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class Parent implements Cloneable {
   private Integer id;
   private String parent_field_1="";
   private String parent_field_2="";
   private List children = new ArrayList();

   
   public Parent(){
      
   }
   
   public Parent(String str_parent_field_1, String str_parent_field_2) {
      parent_field_1 = str_parent_field_1;
      parent_field_2 = str_parent_field_2;
   }

   public void addChildren (Child oneChild){
      if (oneChild == null)
         throw new IllegalArgumentException("Can't add a null child.");
      if (oneChild.getParent() != null && oneChild.getParent().equals(this))
          throw new IllegalArgumentException("child is already in this parent");
      else if (oneChild.getParent() != null){
          // on pourrait ajouter un test sur les conditions de contrats
          oneChild.getParent().removeChildren(oneChild);
      }
      oneChild.setParent(this);
      this.getChildren().add(oneChild);   
    }
   
    public void removeChildren (Child oneChild){
      if (oneChild == null)
         throw new IllegalArgumentException("Can't add a null child.");     
      oneChild.setParent(null);
      this.getChildren().remove(oneChild);
    }
   
   
   public List getChildren() {
      return children;
   }

   public void setChildren(List children) {
      this.children = children;
   }

   public String getParent_field_1() {
      return parent_field_1;
   }

   public void setParent_field_1(String chield_fiel_1) {
      this.parent_field_1 = chield_fiel_1;
   }

   public String getParent_field_2() {
      return parent_field_2;
   }

   public void setParent_field_2(String chiled_field_2) {
      this.parent_field_2 = chiled_field_2;
   }

   public Integer getId() {
      return id;
   }

   public void setId(Integer id) {
      this.id = id;
   }
   
   protected Object clone() {      
            try {
                //Clone the parent.
                Parent p = (Parent)super.clone();
                //Clone the list.
                p.children = (ArrayList)((ArrayList)children).clone();
                for(int i = 0; i < this.children.size(); i++) {
                   p.children.set(i, ((Child)p.children.get(i)).clone());
                }             
                return p; //Return the clone.
            } catch (CloneNotSupportedException e) {
                //This shouldn't happen because Parent and
                //ArrayList implement Cloneable.
                throw new AssertionError();
            }
        }
   
   public String toString() {     
       StringBuffer strb = new StringBuffer();
         strb.append("Parent [");
         strb.append(" | id: "+ getId());
         strb.append(" | Parent_field_1: "+getParent_field_1());
         strb.append(" | Parent_field_2: "+getParent_field_2());
         strb.append("]");
         for (Iterator iter = getChildren().iterator(); iter.hasNext();) {
            Object element = (Object) iter.next();
            strb.append("\n");
            strb.append(" --> "+element);
         
      }   
       return strb.toString();
    }
   
   
   

}



Quote:
Child.java


Code:
package test.clone;

import java.util.ArrayList;


public class Child implements Cloneable{
   
   private Integer id;
   private String child_field_1="";
   private String child_field_2="";
    private Parent parent;
   
   public Child(){
      
   }
   
   public Child(String str_child_field_1, String str_child_field_2) {
      child_field_1 = str_child_field_1;
      child_field_2 = str_child_field_2;
   }

   public Parent getParent() {
      return parent;
   }

   public void setParent(Parent parent) {
      this.parent = parent;
   }

   public String getChild_field_1() {
      return child_field_1;
   }

   public void setChild_field_1(String child_field_1) {
      this.child_field_1 = child_field_1;
   }

   public String getChild_field_2() {
      return child_field_2;
   }

   public void setChild_field_2(String child_field_2) {
      this.child_field_2 = child_field_2;
   }

   public Integer getId() {
      return id;
   }

   public void setId(Integer id) {
      this.id = id;
   }

   
   protected Object clone() {      
        try {
            //Clone the Child.
            return (Child)super.clone();

        } catch (CloneNotSupportedException e) {
            //This shouldn't happen because Child and
            //ArrayList implement Cloneable.
            throw new AssertionError();
        }
    }
   
   public String toString() {     
       StringBuffer strb = new StringBuffer();
         strb.append("Child [");
         strb.append(" | id: "+ getId());
         strb.append(" | idParent: "+getParent().getId());
         strb.append(" | Child_field_1: "+getChild_field_1());
         strb.append(" | Child_field_2: "+getChild_field_2());
         strb.append("]");
       return strb.toString();
    }

}


PS : Java Standard tutorial:
http://penserenjava.free.fr/pens_2.4/indexMain83ff.html?chp=17&pge=01


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jun 15, 2006 5:01 pm 
Expert
Expert

Joined: Thu Dec 23, 2004 9:08 pm
Posts: 2008
For the ArrayList problem: never cast to a concrete implementation, even if it's your own (and in this case, it's not your own, so it's even more important). Cast to List or Collection instead of ArrayList.

For the rules on clone(), the first source of information is the javadocs for clone(). Have a look in your jdk's api docs for those. You could also trawl the internet. I googled "java clone copy constructor" and found many links to interesting articles on the first page alone. There are 830000 results from the search, so there should be something useful in there.

_________________
Code tags are your friend. Know them and use them.


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