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.  [ 9 posts ] 
Author Message
 Post subject: "You may not change the reference to a collection with.
PostPosted: Mon May 10, 2004 4:56 am 
Regular
Regular

Joined: Tue Jan 13, 2004 4:57 am
Posts: 83
Scenario: I have a Customer object which is attached to many UserLogin entities with a all-delete-orphan collection. I have a test where a newly created customer goes through a number of updates without problems. But if I re-load the customer object using the same id, and try to re-do some of those operations, I receive the 'you may not change the reference to a collection with cascade="all-delete-orphan"' error, but I do NOT change that collection in any of my tests! What am I doing wrong?

The error occurs while I try to execute:
Code:
            customer = ( Customer )partyService.getPersonById( partyId );

            relatives = new HashMap();
            relTypeId = partyContainer.partyRelationshipType[ 0 ].getEnumId();
            relatives.put( relative1, relTypeId );

            String newSurname3 = "foo";
            String newForename3 = "bar";
            customer.setSurname( newSurname3 );
            customer.setForename( newForename3 );

            partyService.updateCustomer( customer, relatives );


And the "updateCustomer" method code is:
Code:
Session session = SessionFactoryUtils.getSession( sessionFactory, false );
try {
        List foundRelatives = getPersonRelatives( customer.getPartyId() );
        session.update( customer );
        for ( int i = 0 ; i < foundRelatives.size() ; i++ ) {
            Person relative = ( Person )foundRelatives.get( i );
            unrelate( customer.getPartyId(), relative.getPartyId() );
            session.delete( relative );
        }
        session.flush( ); // absolutely not sure why, but without this it doesn't work
        PartyUtils.setPersonRelatives( customer, relatives );
        saveRelatives( relatives );
}
catch ( HibernateException e ) {
      throw SessionFactoryUtils.convertHibernateAccessException( e );
}


the exception is:
Code:
org.springframework.orm.hibernate.HibernateSystemException: You may not change the reference to a collection with cascade="all-delete-orphan"; nested exception is net.sf.hibernate.HibernateException: You may not change the reference to a collection with cascade="all-delete-orphan"
net.sf.hibernate.HibernateException: You may not change the reference to a collection with cascade="all-delete-orphan"
   at net.sf.hibernate.impl.SessionImpl.prepareCollectionForUpdate(SessionImpl.java:2919)
   at net.sf.hibernate.impl.SessionImpl.updateReachableCollection(SessionImpl.java:2856)
   at net.sf.hibernate.impl.FlushVisitor.processCollection(FlushVisitor.java:32)
   at net.sf.hibernate.impl.AbstractVisitor.processValue(AbstractVisitor.java:69)
   at net.sf.hibernate.impl.AbstractVisitor.processValues(AbstractVisitor.java:36)
   at net.sf.hibernate.impl.SessionImpl.flushEntity(SessionImpl.java:2556)
   at net.sf.hibernate.impl.SessionImpl.flushEntities(SessionImpl.java:2422)
   at net.sf.hibernate.impl.SessionImpl.flushEverything(SessionImpl.java:2224)
   at net.sf.hibernate.impl.SessionImpl.flush(SessionImpl.java:2203)
   at net.sf.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:61)
   at org.springframework.orm.hibernate.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:386)
   at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:316)
   at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:189)
   at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:138)
   at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:148)
   at $Proxy1.updateCustomer(Unknown Source)
   at it.esselunga.ecommerce.services.party.TestSpringHibernatePartyService.testUpdateCustomer(TestSpringHibernatePartyService.java:503)
   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 junit.textui.TestRunner.doRun(TestRunner.java:116)
   at com.intellij.rt.execution.junit2.IdeaJUnitAgent.doRun(Unknown Source)
   at junit.textui.TestRunner.start(TestRunner.java:172)
   at com.intellij.rt.execution.junit.TextTestRunner2.startRunnerWithArgs(Unknown Source)
   at com.intellij.rt.execution.junit2.JUnitStarter.prepareStreamsAndStart(Unknown Source)
   at com.intellij.rt.execution.junit2.JUnitStarter.main(Unknown Source)


And if I stop the debugger when the exception is thrown, I see that the collection where the problem occurs is userLogins, which is not touched by the code above!


Top
 Profile  
 
 Post subject:
PostPosted: Mon May 10, 2004 5:15 am 
Regular
Regular

Joined: Tue Jan 13, 2004 4:57 am
Posts: 83
Another thing which I find strange is the fact that the getPersonById method loads Customer objects with the following code:

Code:
        List result = Session.find( "from Party party where party.partyId=?", partyId, Hibernate.INTEGER );


but just after the method (and after the session close), if I stop the debugger and look into the Customer object (which is a Party subclass), the userLogins collection is populated, although the mapping explicitly sets lazy to true, as the following snippet shows:

Code:
            <set name="userLogins" lazy="true" inverse="true" cascade="all-delete-orphan">
                <key column="PARTY_ID"/>
                <one-to-many class="it.esselunga.ecommerce.data.model.UserLogin"/>
            </set>


what is happening?!?


Top
 Profile  
 
 Post subject:
PostPosted: Mon May 10, 2004 5:26 am 
Regular
Regular

Joined: Tue Jan 13, 2004 4:57 am
Posts: 83
Nevermind the second problem: as I cannot reproduce it I think I should have inadvertently loaded the userLogin collection while looking at the variable in the debugger in the middle of a session. Nevertheless, I can't understand why I receive that exception: is all-delete-orphan compatible with a use as the one I do?


Top
 Profile  
 
 Post subject:
PostPosted: Mon May 10, 2004 5:52 am 
Regular
Regular

Joined: Tue Jan 13, 2004 4:57 am
Posts: 83
BTW: setting that collection to "all" instead of "all-delete-orphan" moves the problem to the following "all-delete-orphan" collection. If I put all of them to "all", the test works as expected.


Top
 Profile  
 
 Post subject:
PostPosted: Mon May 10, 2004 6:42 am 
Regular
Regular

Joined: Tue Jan 13, 2004 4:57 am
Posts: 83
More investigation shows that the problem lies in the userLogins collection for the relative object. I.e.: a customer A is related to a person B, which has a userLogins property which is not touched in the code. The problem lies in SessionImpl:2933, where

Code:
entry.currentPersister.getKeyType().equals(entry.loadedKey, entry.currentKey)


returns false. I'll try to understand why, now.


Top
 Profile  
 
 Post subject:
PostPosted: Mon May 10, 2004 7:04 am 
Regular
Regular

Joined: Tue Jan 13, 2004 4:57 am
Posts: 83
Ok, we're getting closer, and it's related to a problem I had some days ago:

the problem was

http://forum.hibernate.org/viewtopic.php?t=930643

the only solution I found was placing the intermediate flush in the code
Code:
        // update the customer, and delete its relatives
        session.update( customer );
        List foundRelatives = getPersonRelatives( customer.getPartyId() );
        for ( int i = 0 ; i < foundRelatives.size() ; i++ ) {
            Person relative = ( Person )foundRelatives.get( i );
            unrelate( customer.getPartyId(), relative.getPartyId() );
            session.delete( relative );
        }
        session.flush(); // absolutely not sure why, but without this it doesn't work
        PartyUtils.setPersonRelatives( customer, relatives );
        saveRelatives( relatives );


If I remove that line I have the exception (which is a unique violation on the primary key of the relationship table which binds the customer to his relatives)

[code]java.sql.BatchUpdateException: ORA-00001: violata restrizione di unicit


Top
 Profile  
 
 Post subject:
PostPosted: Mon May 10, 2004 7:17 am 
Regular
Regular

Joined: Tue Jan 13, 2004 4:57 am
Posts: 83
No, the problem is not a relationship saved twice, apparently the problem is a relationship that should be deleted and then re-saved, but apparently the delete is not performed?!?

[code]13:11:39,098 DEBUG [SQL] delete from PARTY_RELATIONSHIP where PARTY_ID_TO=? and FROM_DATE=? and THRU_DATE=? and DESCRIPTION=? and RELATIONSHIP_TYPE_ID=? and PARTY_ID_FROM=?
Hibernate: delete from PARTY_RELATIONSHIP where PARTY_ID_TO=? and FROM_DATE=? and THRU_DATE=? and DESCRIPTION=? and RELATIONSHIP_TYPE_ID=? and PARTY_ID_FROM=?
13:11:39,098 DEBUG [BatcherImpl] preparing statement
13:11:39,098 DEBUG [IntegerType] binding '58333' to parameter: 1
13:11:39,098 DEBUG [IntegerType] binding '58333' to parameter: 1
13:11:39,098 DEBUG [TimestampType] binding null to parameter: 2
13:11:39,098 DEBUG [TimestampType] binding null to parameter: 2
13:11:39,098 DEBUG [TimestampType] binding null to parameter: 3
13:11:39,098 DEBUG [TimestampType] binding null to parameter: 3
13:11:39,098 DEBUG [StringType] binding null to parameter: 4
13:11:39,098 DEBUG [StringType] binding null to parameter: 4
13:11:39,108 DEBUG [Cascades] id unsaved-value strategy NULL
13:11:39,108 DEBUG [IntegerType] binding '2294' to parameter: 5
13:11:39,108 DEBUG [IntegerType] binding '2294' to parameter: 5
13:11:39,108 DEBUG [Cascades] id unsaved-value strategy NULL
13:11:39,108 DEBUG [IntegerType] binding '58335' to parameter: 6
13:11:39,108 DEBUG [IntegerType] binding '58335' to parameter: 6
13:11:39,108 DEBUG [BatcherImpl] Adding to batch
13:11:39,108 DEBUG [BasicCollectionPersister] done deleting collection rows: 1 deleted
13:11:39,108 DEBUG [BasicCollectionPersister] Updating rows of collection: it.esselunga.ecommerce.data.model.Party.relatedPartiesFrom#58333
13:11:39,108 DEBUG [BasicCollectionPersister] done updating rows: 0 updated
13:11:39,108 DEBUG [BasicCollectionPersister] Inserting rows of collection: [it.esselunga.ecommerce.data.model.Party.relatedPartiesFrom#58333]
13:11:39,108 DEBUG [BatcherImpl] Executing batch size: 1
13:11:39,118 DEBUG [BatcherImpl] success of batch update unknown: 0
13:11:39,118 DEBUG [BatcherImpl] done closing: 0 open PreparedStatements, 0 open ResultSets
13:11:39,118 DEBUG [BatcherImpl] closing statement
13:11:39,128 DEBUG [BatcherImpl] about to open: 0 open PreparedStatements, 0 open ResultSets
13:11:39,128 DEBUG [SQL] insert into PARTY_RELATIONSHIP (PARTY_ID_TO, FROM_DATE, THRU_DATE, DESCRIPTION, RELATIONSHIP_TYPE_ID, PARTY_ID_FROM) values (?, ?, ?, ?, ?, ?)
Hibernate: insert into PARTY_RELATIONSHIP (PARTY_ID_TO, FROM_DATE, THRU_DATE, DESCRIPTION, RELATIONSHIP_TYPE_ID, PARTY_ID_FROM) values (?, ?, ?, ?, ?, ?)
13:11:39,128 DEBUG [BatcherImpl] preparing statement
13:11:39,128 DEBUG [IntegerType] binding '58333' to parameter: 1
13:11:39,128 DEBUG [IntegerType] binding '58333' to parameter: 1
13:11:39,128 DEBUG [TimestampType] binding null to parameter: 2
13:11:39,128 DEBUG [TimestampType] binding null to parameter: 2
13:11:39,128 DEBUG [TimestampType] binding null to parameter: 3
13:11:39,128 DEBUG [TimestampType] binding null to parameter: 3
13:11:39,128 DEBUG [StringType] binding null to parameter: 4
13:11:39,128 DEBUG [StringType] binding null to parameter: 4
13:11:39,128 DEBUG [Cascades] id unsaved-value strategy NULL
13:11:39,128 DEBUG [IntegerType] binding '2294' to parameter: 5
13:11:39,128 DEBUG [IntegerType] binding '2294' to parameter: 5
13:11:39,128 DEBUG [Cascades] id unsaved-value strategy NULL
13:11:39,138 DEBUG [IntegerType] binding '58335' to parameter: 6
13:11:39,138 DEBUG [IntegerType] binding '58335' to parameter: 6
13:11:39,138 DEBUG [BatcherImpl] Adding to batch
13:11:39,138 DEBUG [BasicCollectionPersister] done inserting rows: 1 inserted
13:11:39,138 DEBUG [BatcherImpl] Executing batch size: 1
13:11:39,168 DEBUG [JDBCExceptionReporter] SQL Exception
java.sql.BatchUpdateException: ORA-00001: violata restrizione di unicit


Top
 Profile  
 
 Post subject:
PostPosted: Mon May 10, 2004 8:21 am 
Regular
Regular

Joined: Tue Jan 13, 2004 4:57 am
Posts: 83
Ok, this depended, I think, on the fact that I passed the method a relative object which was already been saved: this probably creates problems with the fact I do re-save the object in another line of my code. How this maps to the "you can't change the reference to a collection with cascade all-delete-orphan" exception message is a mistery, though.


Top
 Profile  
 
 Post subject:
PostPosted: Mon May 10, 2004 12:32 pm 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
Hibernate keep state in collection when using all-delete-orphan, so you must not dereference the collection (new instance), otherwise it is lost.

_________________
Emmanuel


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