Il 02/03/2016 15:59, christopher
delahunt ha scritto:
Hello Mauro,
I mistyped when I wrote cascade remove - I meant to write cascade
merge or cascade persist. Any references to 'first' could be
causing it to be resurrected, not just ones from the 'second'
instance's object graph. I also noticed you are using cascade
refresh and lazy relationships - refresh of the referenced entity
over a lazy reference will be delayed until it is accessed,
potentially wiping out changes made so far. Something that causes
a refresh of firstCollection for instance might get triggered
after the remove call but before the flush, and cause
firstCollection to still reference first and cause its
resurrection in the persistence unit. I would detail all the
references in your object model to the 'first' class and check
that one isn't interfering.
If you haven't already, I'd recommend turning on EclipseLink
logging and matching statements up to the calls in your code
causing them, and trying to determine what is different when the
issue occurs vs when it doesn't. You might also try delaying or
removing the constraint, so that you can see if EclipseLink
eventually issues the delete so we can see if it is just an
ordering issue or if it never does, and so is a resurrection issue
in the application references as mentioned before.
Best of luck,
Chris
Hi Chris,
I was "lucky enough" to be able today to reproduce this issue
locally!! It's very hard to know what is the correct reproduction
path, anyway... What I observed by debugging is this:
FirstCollection firstCollection = first.getFirstCollection();
// do some read-only operations on first
// remove first from the FirstCollection related
entities
firstCollection.getFirsts().remove(first);
// delete first
entityManager.remove(first);
// added a flush in the hope this fixes the problem
entityManager.flush(); (***)
// delete the related second instance
entityManager.remove(first.getSecond());
// perform a read query on an entity related to first
Stepping over (***) I saw that the only query that was executed was
an UPDATE on the FirstCollection table to update the version and
lastUpdated fields!!! The DELETE FROM First was not issued at all!
So, this makes me suspect that the problem is what you are saying:
"Something that causes a refresh of firstCollection for instance
might get triggered after the remove call but before the flush, and
cause firstCollection to still reference first and cause its
resurrection in the persistence unit"
So, I removed the cascade=REFRESH from the relationships in
FirstCollection and Third that referenced the First entity.
However, I'm not sure whether it will work now or not because I
can't reproduce any more.
In fact, I was able to correctly perform the whole deletion once by
using this code:
FirstCollection firstCollection = first.getFirstCollection();
// do some read-only operations on first
// remove first from the FirstCollection related
entities
firstCollection.getFirsts().remove(first);
// first flush
entityManager.flush();
// delete first
entityManager.remove(first);
// second flush
entityManager.flush();
// delete the related second instance
entityManager.remove(first.getSecond());
// perform a read query on an entity related to first
that is, by performing a first flush before the remove (this caused
just the UPDATE on the FirstCollection table!) and a second one
after the remove operation (this one actually performed the DELETE
FROM First statement!). But having two flushes like this sounded too
dirty for me, so I decided to try the removal of the cascade=REFRESH
thing.
I will monitor the situation for some days and let you know. Anyway,
if the cascade=REFRESH is the actual problem, this is a really bad
beast... especially because I'm really doing nothing in between the
remove and the flush. Also, I would expect
firstCollections.getFirsts() to be already loaded into memory
because it has been accessed several times before and the shared
cache is enabled, so I don't even expect it to be lazy initialised
when I'm calling that code. So, there's quite a lot of (black)
magic here... :-(
And I can't explain exactly why two flushes before and after the
remove would fix the problem.
Mauro
|