Home » Eclipse Projects » EclipseLink » Sporadic and arbitrary DELETES issued by EclipseLink(EclipseLink 2.4.1 sporadically deletes arbitrary rows from database)
Sporadic and arbitrary DELETES issued by EclipseLink [message #1044035] |
Thu, 18 April 2013 12:13 |
Markus KARG Messages: 28 Registered: June 2011 |
Junior Member |
|
|
When we run the same use case again and again in our lab, in about 25% of all attempts EclipseLink is running a DELETE command against the database -- but actually the use case does not imply any deletion at all!
Scenario:
returns a tree like this:
A
!
+---B1
! !
! +---C
! !
! +---D
!
+---B2
then we move the "C--D" branch from B1 to B2 using:
C.setParent(B2);
B2.add(C);
B1.remove(C);
Then we merge the whole tree:
Actual Result:
In all cases, EclipseLink 2.4.1 (and 2.3.3) correctly does:
UPDATE C SET PARENT_B_ID = B1 WHERE ...
But in 25% of all cases (and they are exactly identical!) EclipseLink *additionally* does:
Hence, it throws away the D row, and we simply do not understand why it does this. And, we do not understand why it does this only in 25% of all cases. Again, we operate always with exactly the same data, so there is no difference in the executed data or algorithm!
While this actually is a showstopper for us and we are really hoping to get any help soon, we identified a workaround: Instead of moving around the "C--D" tree, we completely clone it, add the clone to B2, and remove the clone's source. As a result, EclipseLink correctly does INSERT on the clone and DELETE on the clone's source. This is working, but everything but smart.
Dear EclipseLink Team: Is this our fault? Then please tell us what we must change!
Thanks a lot!
-Markus
|
|
| |
Re: Sporadic and arbitrary DELETES issued by EclipseLink [message #1044155 is a reply to message #1044068] |
Thu, 18 April 2013 15:00 |
Markus KARG Messages: 28 Registered: June 2011 |
Junior Member |
|
|
Chris,
thank you for picking this up. Here are the answers to your questions.
Relationships:
B, C and D are actually all instances of the same entity type T, which implements a self-reference ("parent-children hierarchy").
This is implemented using a bi-directional relationship between T and itself. But this bi-directionality is implemented in two classes.
T implements the link to the parent (single side). T's super class U implements the children collection (multi side).
...class T extends U...:
@NotNull @XmlTransient @ManyToOne @JoinColumn(name = "parent_id", referencedColumnName = "ID")
private U parent;
...class U...:
@XmlElement(name = "...") @OneToMany(mappedBy = "parent", cascade = ALL, orphanRemoval = true) @OrderBy("sequenceIndex")
private List<T> children = new LinkedList<T>();
Version:
Discovered in EclipseLink 2.3.3 but still happens in EclipseLink 2.4.4. Note that we use it in GlassFish 3.1.1 as part of a EAR.
Does it remove C:
No it never removes C. It only removes D. And if D has children E of type T, then sometimes it removes D and E, but sometimes it only removes E but keeps D. And, again, most of the time it does not remove anything at all but simply works correctly.
Reinsertion Attempt:
We do not see any INSERT logged, but only the DELETE of D (DELETE FROM T followed by DELETE FROM U).
Does it happen on flush:
As we run withing an EJB we do not invoke flush() or commit() but let GlassFish's TX control decide. Do you want us to explicitly flush() at the end of the business method? And what do you mean with "flushing again"?
Thanks so much!
-Markus
|
|
|
Re: Sporadic and arbitrary DELETES issued by EclipseLink [message #1044187 is a reply to message #1044155] |
Thu, 18 April 2013 15:40 |
Chris Delahunt Messages: 1389 Registered: July 2009 |
Senior Member |
|
|
By flush again, I mean call flush twice. This will determine if it is an issue with how the entity is found, which might depends on how the object graph is traversed. If it discovers the C+D in B2, and then processes B1, it will force the delete to occur due to the orphan removal setting, and then cascade it over all its children due to your cascade settings. I suspect that the object graph traversal is non-deterministic, so that the problem only occurs when B2 is processed before B1. Other cascade persist/merge relationships might be causing C to be resurrected before the delete statement is issued. Its difficult to surmise what might be happening in a complex model that only reproduces occasionally.
The cause though is the orphan removal setting. You should not be using Orphan removal if you are going move entities between relationships. Orphan removal is equivalent to EclipseLink's private ownership, and means that the entities should only exist when referenced by their parent. If you must keep this, you can removing C from B1, flush, and then associate C to B2. This should result in delete statements in the first flush, followed by inserts in when the transaction commits or is flushed again.
Best Regards,
Chris
|
|
|
Re: Sporadic and arbitrary DELETES issued by EclipseLink [message #1044678 is a reply to message #1044187] |
Fri, 19 April 2013 07:44 |
Markus KARG Messages: 28 Registered: June 2011 |
Junior Member |
|
|
Chris,
we have checked what you asked us for, and here are the results:
* Double em.flush() after em.merge(): This still produces the problem! We did not see any improvement over not manually flushing at all.
* Setting orphanRemoval=true: The problem is not reproducible anymore when stopping to remove orphans!
While from the view of a former TopLink contributor it is great to see that you are on track of finding the root cause, from the view of an application vendor I still do not see any approach to work around the issue other than what we do currently (manually DELETE+INSERT, what actually means, producing a version-less clone), which actually is not really satisfying as you can imagine. The reason is the application's actual architecture. I'd like to explain in short so you see the problem: The modifications are not done by any Java code on the server, but are done by editing a XML file on the client (imagine using a simple editor). Then, the XML file is sent to the server. What the server does is nothing else but em.merge(unmarshal(xml)). We just told the steps in pseudo-Java-code to make clear what the users does in XML (in fact, the user has a Java based editor which in fact does that code, but in the end, what comes out IS pure XML but not JPA commmands). So, we cannot go the way you described. When we stop orphan removal, then orphans will stay in the database. And we cannot flush between the single edit steps since we get back the completely edited XML as one single step -- and we cannot know what actual edits are done by the user at runtime. BTW, it is really scary to read that one cannot predict whether EclipseLink would do UPDATE vs. INSERT+DELETE, as the latter could imply real problems in case there are foreign key constraints, removing any non-JPA-controlled rows in turn... but this is a different topic! This really scares me (good luck, we do not have such a problem currently).
So looking from the users and application vendor's view, this is clearly a bug of EclipseLink, as the application vendor must rely on the terms of the JPA spec, which coarsely says that one has to issue em.merge() and that's all to get things done. If that is not what EclipseLink wants the spec to be understood I would be happy to file a spec issue, but for now, we need to find a *working* solution.
From what you wrote I assume that the following should work: Asking the user to set the version field to zero before uploading (which is what effectively happens by our current solution of cloning the entity). If I understand EclipseLink's behaviour, then that *deterministically* results in DELETE of the now-orphans followed by an INSERT of the clone ALWAYS -- so we could simply ask the user to set the version to zero instead of really "clone" the XML branch.
BTW, if orphan removal is the sole problem then I wonder why you actually traverse the tree at all and why you think you must remove orphans "at once". You could either move the detection of orphans to the end (so it becomes deterministic AND makes clear that no orphans are created by chaning the parent), or simply replace the algorithm by offloading this to the server (issue a "DELETE FROM Table WHERE parent is NULL" as very the last command of the TX).
As you see, we really are glad that you picked up this thread to help us, but we do not see a real solution besides a bug fix in EclipseLink: Orphan removal must be predicted by doing at as the last step, not doing it any time "within".
Thanks!
-Markus
|
|
| | | |
Re: Sporadic and arbitrary DELETES issued by EclipseLink [message #1044969 is a reply to message #1044961] |
Fri, 19 April 2013 15:17 |
Markus KARG Messages: 28 Registered: June 2011 |
Junior Member |
|
|
You still misunderstand the actual situation. As the spec says: "If an entity that is the target of the relationship is removed from the relationship BY SETTING THE RELATIONSHIP TO NULL OR REMOVING THE ENTITY FROM THE RELATIONSHOP COLLECTION..." -- We do NEITHER. We do not remove C. We do not set D's parent to NULL. We do nothing of this. I would agree with you, if we would remove B or C. But we do not! So this section does not apply to D. And we talk about D vanishing, while it is C which changes the parent, remember? Also, as I said, we solely do merge() on a previously detached object so to cite again your cite: " If the entity being orphaned is a detached, new, or removed entity, the semantics of orphanRemoval do not apply.". As a matter of fact: EclipseLink voids this last line!
And once more: We do not DELETE the owner. Both owners (old and new) still exist! "Privately owned" only means "Remove D if C is removed", but not "Remove D if C moves from B1 to B2"!
|
|
|
Re: Sporadic and arbitrary DELETES issued by EclipseLink [message #1045042 is a reply to message #1044969] |
Fri, 19 April 2013 17:32 |
Chris Delahunt Messages: 1389 Registered: July 2009 |
Senior Member |
|
|
As stated, your model is complex. I surmised that the cause of D being deleted is because of C being disassociated from its parent relationship which is marked for orphan removal, and the C->D relationship marked with cascade persist. That is the basis of my comments, and you have only confirmed this by stating that removing the orphan removal setting resolves the issue.
Private ownership does not mean only delete if it isn't referenced by anyone else, or the specification would not include: "Portable applications must otherwise not depend upon a
specific order of removal, and must not reassign an entity that has been orphaned to another
relationship or otherwise attempt to persist it", which is exactly what your application is relying on. If you disassociate C from B and reassign it to a different B, what happens is completely dependent on the order those changes are processed by the JPA provider. Private owned means it is privately owned by the referencing entity, and should not be shared or passed around. It is dead to the JPA spec once dissociated.
As B1 and C are not detached, removed or new, the semantics of orphan removal absolutely apply. Your act of merging in B1 brings in C and will dereference it.
|
|
| |
Re: Sporadic and arbitrary DELETES issued by EclipseLink [message #1045443 is a reply to message #1045042] |
Sat, 20 April 2013 08:43 |
Markus KARG Messages: 28 Registered: June 2011 |
Junior Member |
|
|
Chris,
thank you for this detailed insight and your Kind help -- and being so patient with me. I think you understand that users get upset and anxious when they see that an otherwise reliable product arbitrary decides to kill valueable business data.
I understand that EclipseLink is unable to "correctly" (from the user's view) deal with the move, and that you assume this is covered by the cited part of the spec (which I in fact read multiple times the last days).
So I will do three things.
First, I am confident our team can provide a portable solution basing on your idea of entity listeners (unfortunately this means doing this again and again for all kinds of entities as I do not see a "generic entity handle" which we could use for a generic solution). In fact we did not think of listeners before, and it implies a lot of work to us (compared to receiving an EclipseLink fix), but in the end it will definitively provide the best end user experience as it results in the fact that the user has no need to care about anything (just uploads the modified files -- "fire and forget") and results in an UPDATE (instead of DELETE+INSERT) at the same time (what is why we actually started this thread). Even this single idea was worth all the discussion, and thank you once more for sharing your ideas with us.
Second, I will file a bug report in the EclipseLink tracker, as I still think that (a) that part of the spec is not applicable to the current case (because actually A is detached at the moment em.merge() occurs), and (b) even if EclipseLink works in accordance to the spec, it is really unacceptable from a user's view that it sporadically and arbitrarily DELETEs valueable business data without any further note to the user. The latter is a worst-case behaviour and my understanding of reliability is that a software must never work in an unexpected way -- but arbitrary DELETE is always unexpected (in the sense of "unintuitive", not in the sense of "not covered by the spec"), even if covered by the spec.
Third, I have invited spec lead Linda DeMichiel to judge about (a) and (b). She asked me to file the bug report and will decide then. If she comes to the decision that I am right (A is detached, hence that spec paragraph does not apply), I assume the EclipseLink team will fix this unexpected behaviour ASAP, saving us from investing lots of time in a solution not necessary anymore then. On the other hand, if she decides that EclipseLink works correct and a user must expect arbitrary DELETEs, I have good arguments in hand to file a RFE against the next spec version -- as this is unacceptable (since absolutely counterintuitive) and should be improved in JPA generally (independent of EclipseLink).
Anyway, thank you so much for the time you invested. It is always worth to discuss with the EclipseLink Team!
Regards
-Markus
|
|
| | |
Goto Forum:
Current Time: Sun Sep 22 03:29:56 GMT 2024
Powered by FUDForum. Page generated in 0.03660 seconds
|