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.  [ 11 posts ] 
Author Message
 Post subject: Copying a Graph Of Objects
PostPosted: Mon Jan 16, 2006 2:21 am 
Newbie

Joined: Fri Jan 13, 2006 1:40 pm
Posts: 11
I have a scenarion where I need to make a copy of the entire Account given the accountId.

I am trying the following approach,

Copying the graph and trying to set the id's to null through the graph

As a first step,
I am trying to copy Account and AccountVersionStatuses which has the
following relationship Account->AccountVersionStatuses *

and ran into the following issues.Your help is valued

Hibernate version:
Hibernate 3.0

Mapping documents:
<hibernate-mapping >
<class name="com.csg.accountsetup.account.model.Account" table="ACCOUNT">
<id name="accountVersionId" type="long">
<column name="ACCOUNT_ID"/>
<generator class="sequence">
<param name="sequence">ACCOUNT_PK_SQ</param>
</generator>
</id>
<version name="optimisticLockVersion" column="VERSION_NUMBER" type="long"/>

<property name="year" type="long">
<column name="YEAR" length="7" />
</property>
<property name="createdDate" type="calendar">
<column name="CREATED_DATE" length="7" />
</property>
<property name="modifiedBy" type="string">
<column name="MODIFIED_BY" length="2048" />
</property>
<property name="lastModifiedDate" type="calendar">
<column name="LAST_MODIFIED" length="7" />
</property>
<property name="descr" type="string">
<column name="DESCR" length="4000" />
</property>
<property name="accountVersion" type="long">
<column name="ACCOUNT_VERSION"/>
</property>
<property name="accountName" type="string">
<column name="ACCOUNT_NAME" length="2048" />
</property>
<property name="addressLine1" type="string">
<column name="ADDRESS_LINE1" length="3000" />
</property>
<property name="addressLine2" type="string">
<column name="ADDRESS_LINE2" length="3000" />
</property>
<property name="city" type="string">
<column name="CITY" length="256" />
</property>
<property name="state" type="string">
<column name="STATE" length="10" />
</property>
<property name="zip" type="string">
<column name="ZIP" length="20" />
</property>
<property name="contactName" type="string">
<column name="CONTACT_NAME" length="2048" />
</property>
<property name="contactEmail" type="string">
<column name="CONTACT_EMAIL" length="1024" />
</property>
<property name="contactPhone" type="string">
<column name="CONTACT_PHONE" length="20" />
</property>
<property name="contactFax" type="string">
<column name="CONTACT_FAX" length="20" />
</property>
<property name="createdBy" insert="false" update="false" type="long">
<column name="CREATED_BY" length="20" />
</property>



<set name="accountVersionStatuses" cascade="all-delete-orphan" inverse="true" lazy="false">
<key>
<column name="ACCOUNT_VERSION_ID" />
</key>
<one-to-many class="com.csg.accountsetup.account.model.AccountVersionStatus" />
</set>




</class>
</hibernate-mapping>
Code between sessionFactory.openSession() and session.close():
public AccountVersion createACopy(Long accountVersionId)
{
AccountVersion copyOfAccountVersion = null;
AccountVersion accountVersion = null;

ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream out;
try
{
accountVersion = viewAccountVersionInfo(accountVersionId);

//Materialize the associations by trying to reach 'em.


Set accountVersionStatuses = accountVersion.getAccountVersionStatuses();
Iterator iterator = accountVersionStatuses.iterator();
out = new ObjectOutputStream(bos);
try
{
out.writeObject(accountVersion);
out.flush();
}
finally
{
out.close();
}

// Retrieve an input stream from the byte array and read
// a copy of the object back in.
ByteArrayInputStream bin = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream in = new ObjectInputStream(bin);

copyOfAccountVersion = (AccountVersion) in.readObject();
}
catch (ClassNotFoundException e)
{
throw new RuntimeException(e);
}

catch (IOException e)
{
throw new RuntimeException(e);
}
catch(CSGBusinessException e)
{
throw new RuntimeException(e);
}

copyOfAccountVersion.setAccountVersionId(null);
copyOfAccountVersion.setOptimisticLockVersion(0);
Set copiedClasses = copyOfAccountVersion.getAccountVersionStatuses();
for (Iterator iter = copiedClasses.iterator(); iter.hasNext();)
{
AccountVersionStatus element = (AccountVersionStatus) iter.next();
element.setAccountVersionStatusId(null);
element.setOptimisticLockVersion(0);


}


getHibernateTemplate().save(copyOfAccountVersion);
getHibernateTemplate().flush();


return copyOfAccountVersion;
}
Full stack trace of any exception that occurs:
java.lang.RuntimeException: org.springframework.orm.hibernate3.HibernateSystemException: Don't change the reference to a collection with cascade="all-delete-orphan": com.csg.accountsetup.account.model.AccountVersion.accountVersionStatuses; nested exception is org.hibernate.HibernateException: Don't change the reference to a collection with cascade="all-delete-orphan": com.csg.accountsetup.account.model.AccountVersion.accountVersionStatuses
at com.csg.accountsetup.account.biz.AccountImpl.createACopy(AccountImpl.java:1418)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:324)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:292)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:155)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:122)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:144)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:174)
at $Proxy8.createACopy(Unknown Source)
at com.csg.accountversion.biz.AccountVersionImplTests.testCopyingUsingSerialization(AccountVersionImplTests.java:38)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:324)
at junit.framework.TestCase.runTest(TestCase.java:154)
at junit.framework.TestCase.runBare(TestCase.java:127)
at junit.framework.TestResult$1.protect(TestResult.java:106)
at junit.framework.TestResult.runProtected(TestResult.java:124)
at junit.framework.TestResult.run(TestResult.java:109)
at junit.framework.TestCase.run(TestCase.java:118)
at junit.framework.TestSuite.runTest(TestSuite.java:208)
at junit.framework.TestSuite.run(TestSuite.java:203)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:478)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:344)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
Caused by: org.springframework.orm.hibernate3.HibernateSystemException: Don't change the reference to a collection with cascade="all-delete-orphan": com.csg.accountsetup.account.model.AccountVersion.accountVersionStatuses; nested exception is org.hibernate.HibernateException: Don't change the reference to a collection with cascade="all-delete-orphan": com.csg.accountsetup.account.model.AccountVersion.accountVersionStatuses
at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:656)
at org.springframework.orm.hibernate3.HibernateAccessor.convertHibernateAccessException(HibernateAccessor.java:413)
at org.springframework.orm.hibernate3.HibernateTemplate.execute(HibernateTemplate.java:320)
at org.springframework.orm.hibernate3.HibernateTemplate.flush(HibernateTemplate.java:726)
at com.csg.accountsetup.account.dao.AccountDAOImpl.saveAccountVersion(AccountDAOImpl.java:583)
at com.csg.accountsetup.account.biz.AccountImpl.createACopy(AccountImpl.java:1414)
... 27 more
Caused by: org.hibernate.HibernateException: Don't change the reference to a collection with cascade="all-delete-orphan": com.csg.accountsetup.account.model.AccountVersion.accountVersionStatuses
at org.hibernate.engine.Collections.prepareCollectionForUpdate(Collections.java:181)
at org.hibernate.engine.Collections.processReachableCollection(Collections.java:149)
at org.hibernate.event.def.FlushVisitor.processCollection(FlushVisitor.java:37)
at org.hibernate.event.def.AbstractVisitor.processValue(AbstractVisitor.java:104)
at org.hibernate.event.def.AbstractVisitor.processValue(AbstractVisitor.java:64)
at org.hibernate.event.def.AbstractVisitor.processEntityPropertyValues(AbstractVisitor.java:58)
at org.hibernate.event.def.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:198)
at org.hibernate.event.def.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:190)
at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:70)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:26)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:730)
at org.springframework.orm.hibernate3.HibernateTemplate$27.doInHibernate(HibernateTemplate.java:728)
at org.springframework.orm.hibernate3.HibernateTemplate.execute(HibernateTemplate.java:315)
... 30 more


Name and version of the database you are using:
Oracle


The generated SQL (show_sql=true):

Laste generated Sql

DEBUG - select ACCOUNT_VERSION_STATUS_PK_SQ.nextval from dual
Debug level Hibernate log excerpt:

Debug


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 16, 2006 5:44 am 
Newbie

Joined: Wed Jan 11, 2006 5:21 am
Posts: 14
why dont you try cloning acount?


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 16, 2006 5:58 am 
Newbie

Joined: Fri Jan 13, 2006 1:40 pm
Posts: 11
I have not used cloning as that takes care of just the shallow Copy and not the deep copy.

Requirement in detail:
If there exists an Account with say 2 AccountVersionStatuses.

My copied Account should also have 2 AccountVersionStatuses with new Account's Id as their foreign Key

In short ,Its a copy of the complete graph .. (taking care of deep copies).

for eg,in this case
A clone of Account would have the accountVersionStatus pointing to the same Set reference as in the original Account.Which is essentially not a copy.As per my requirement I need to make a copy of accountVersionStatuses also.


Top
 Profile  
 
 Post subject: Cloning....
PostPosted: Mon Jan 16, 2006 7:30 am 
And why don't you implement the "deep" copy inside your clone method???????


Cheers,


:Luiz.


Top
  
 
 Post subject:
PostPosted: Mon Jan 16, 2006 7:45 am 
Newbie

Joined: Fri Jan 13, 2006 1:40 pm
Posts: 11
I tried implementing the deep copy myself and ran into following issues,

1.The set of child Objects when they are cloned we need
to take care of setting the new parent to them

2.The graph shown above is just a portion of it,and the account actually constitutes much more dependencies like UserAccount which is a many to many relationship between Account and User,and many more
dependecies specific to project requirement..


3.deep Down the graph when I have a cyclic interdepencies it complicates
the logic to avoid traversing
a)through the same node again and taking a clone of the same object again ..thereby we dont end up having a copy of the same object twice.

or b) traversing them back and forth causing stackoverflowerror

setting the dependencies need to taken care of by us.which involves more code and the possibility of bug increases

but when we use serialization approach,the dependencies are taken care of across the graph.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 16, 2006 9:08 am 
Newbie

Joined: Fri Jan 13, 2006 1:40 pm
Posts: 11
I have tried to set the cascade settings to "all" instead of "all-delete-orphan" and is found to work.I am unable to explain the behaviour.As these objects have dependencies on other use cases the cascade setting needs to be cascade="all-delete-orphan".Can you please suggest on the same

Any help is valued.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jan 17, 2006 5:04 am 
Regular
Regular

Joined: Tue Dec 14, 2004 5:21 am
Posts: 104
Location: india
hibernate record the collection role that this collection is referenced by
and decide if the collection needs deleting/creating/updating (ref: cascade)

orphaned delete (here) causes the reference to a collection to be lost

why not try a DTO like stuff ( i may be wrong :) )

_________________
sHeRiN
thanks for your ratings ...... :)


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jan 17, 2006 11:00 am 
Newbie

Joined: Fri Jan 13, 2006 1:40 pm
Posts: 11
Thanks for your reply.. I am a new bie and I could not understand the explanation given above.. Please any one of you give a better explanation or point me to some location with explanation


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jan 17, 2006 11:02 am 
Newbie

Joined: Fri Jan 13, 2006 1:40 pm
Posts: 11
yeshvanthni wrote:
Thanks for your reply.. I am a new bie and I could not understand the explanation given above.. Please any one of you give a detail explanation or point me to some location with explanation


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jan 17, 2006 11:02 am 
Newbie

Joined: Fri Jan 13, 2006 1:40 pm
Posts: 11
yeshvanthni wrote:
Thanks for your reply.. I am a new bie and I could not understand the explanation given above.. Please any one of you give a detail explanation or point me to some location with explanation


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jan 18, 2006 12:00 pm 
Regular
Regular

Joined: Tue Dec 14, 2004 5:21 am
Posts: 104
Location: india
yeshvanthni wrote:
yeshvanthni wrote:
Thanks for your reply.. I am a new bie and I could not understand the explanation given above.. Please any one of you give a detail explanation or point me to some location with explanation


i was talking about Data Transfer Objects as an alternative . i'm afraid if i can provide u the references u need at this time . coz i have never been in ur situation . i'll be happy to post if i find a suitable solution .

_________________
sHeRiN
thanks for your ratings ...... :)


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