-->
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.  [ 2 posts ] 
Author Message
 Post subject: 4.2.6 upgrade removes an entry from a OneToMany collection
PostPosted: Fri Oct 04, 2013 3:28 pm 
Newbie

Joined: Mon Sep 24, 2007 8:11 am
Posts: 16
I am testing the upgrade of Hibernate from 3.3.2 to 4.2.6.Final. I made the few required changes (CollectionOfElements to ElementCollection, etc..)
and everything seems to be working, with the exception of one Junit test (which has not given us problems before). I have the same issue running the
unit test against Hypersonic and MSSQL databases.
The test removes the last entry from a persisted list, that has 2 entries on it. When the transaction commits, some code in Hibernate seems to have
removed the first item from the list as well, and I get an ObjectDeletedException, complaining about the first entry on the list.
Below are the relevant parts of the 2 classes - a VmBackup contains a list of Snapshots.
Code:
public class VmBackup
{
    @OneToMany(mappedBy = "vmBackup", cascade = CascadeType.ALL)
    @OrderBy()
    private List<Snapshot> backups = new ArrayList<Snapshot>();
}

Code:
public class Snapshot
{
    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    private VmBackup vmBackup;

}


Below is the code that removes the last snapshot from the list:
Code:
   public void deleteSnapshot()
   {
        List<Snapshot> snapshots = getBackups();

        // Walk the list backwards, since we are removing items from it as we go       
        for (int i = snapshots.size() - 1; i >= 0; i--)
        {
            Snapshot snapshot = snapshots.get(i);
            if (snapshot.getId().equals(restorePointId))
            {
                LOG.info("Deleting snapshot " + snapshot.toString());
               
                // Remove the snapshot from the list of backups
                snapshot = backups.remove(i);
                session.delete(snapshot);
            }
        }
   }


I've run the test thru Eclipse and set a breakpoint at the session.delete line. The call stack is as follows:
Quote:
deleteSnapshot
NativeMethodAccessorImpl.invoke()
NativeMethodAccessorImpl.invoke()
DelegatingMethodAccessorImpl()
Method.invoke()
JavassistLazyInitializer.invoke()
VmBackup_$$_javassist_29.deleteSnapshot
completeRestorePoint


If I look at the list when the deleteSnapshot method exits, there is the single entry on it, as there should be.
When the code returns to that last method on the call stack (completeRestorePoint), the list is empty, so somewhere in the
code on the call stack, the additional entry is removed from the list.

Below are what I believe are the relevant log messages from Hibernate, and the stack trace when I try to commit the transaction.
Snapshot#1 is the entry on the list that was not deleted by my code.

Quote:
2013-10-04 14:58:30,115 TRACE: Processing cascade ACTION_SAVE_UPDATE for: com.vc.mgmt.api.backup.VmBackup [Cascade[main]]
2013-10-04 14:58:30,115 TRACE: Cascade ACTION_SAVE_UPDATE for collection: com.vc.mgmt.api.backup.VmBackup.backups [Cascade[main]]
org.hibernate.ObjectDeletedException: deleted object would be re-saved by cascade (remove deleted object from associations): [com.vc.mgmt.api.backup.Snapshot#1]
at org.hibernate.internal.SessionImpl.forceFlush(SessionImpl.java:1247)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:184)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:114)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:90)
at org.hibernate.internal.SessionImpl.fireSaveOrUpdate(SessionImpl.java:735)
at org.hibernate.internal.SessionImpl.saveOrUpdate(SessionImpl.java:727)
at org.hibernate.engine.spi.CascadingAction$5.cascade(CascadingAction.java:258)
at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:388)
at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:331)
at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:209)
at org.hibernate.engine.internal.Cascade.cascadeCollectionElements(Cascade.java:418)
at org.hibernate.engine.internal.Cascade.cascadeCollection(Cascade.java:358)
at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:334)
at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:209)
at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:166)
at org.hibernate.event.internal.AbstractFlushingEventListener.cascadeOnFlush(AbstractFlushingEventListener.java:162)
at org.hibernate.event.internal.AbstractFlushingEventListener.prepareEntityFlushes(AbstractFlushingEventListener.java:153)
at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:89)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:51)
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1234)
at com.vc.mgmt.api.TxFactory.commitTransaction(TxFactory.java:352)
at com.vc.mgmt.control.ControlServlet.handleRequest(ControlServlet.java:446)


Top
 Profile  
 
 Post subject: Re: 4.2.6 upgrade removes an entry from a OneToMany collection
PostPosted: Mon Oct 07, 2013 9:57 am 
Newbie

Joined: Mon Sep 24, 2007 8:11 am
Posts: 16
I found the problem - we optionally reference the Snapshot from another class (see below), if it is selected by the user. This reference had a cascade-delete specified, which was unnecessary and incorrect. In the failing Junit test, the reference was set to null, which caused the deletion.
Altho Hibernate apparently did not enforce the cascade in previous releases, as this code has not changed. I will have to take a closer look at other associations that we mark as cascade-delete to make sure we don't see other subtle problems.
This association should also probably be a ManyToOne.

Code:
    @OneToOne(optional = true, cascade = CascadeType.ALL)
    @Cascade( { org.hibernate.annotations.CascadeType.DELETE_ORPHAN })
    private Snapshot restorePoint = null;


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