Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » EclipseLink » Sporadic and arbitrary DELETES issued by EclipseLink(EclipseLink 2.4.1 sporadically deletes arbitrary rows from database)
icon5.gif  Sporadic and arbitrary DELETES issued by EclipseLink [message #1044035] Thu, 18 April 2013 12:13 Go to next message
Markus KARG is currently offline Markus KARGFriend
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! Shocked

Scenario:

em.find(A.class, ...)


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:

em.merge(A);


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:

DELETE FROM D WHERE ...


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. Confused

Dear EclipseLink Team: Is this our fault? Then please tell us what we must change! Smile

Thanks a lot!
-Markus
Re: Sporadic and arbitrary DELETES issued by EclipseLink [message #1044068 is a reply to message #1044035] Thu, 18 April 2013 13:08 Go to previous messageGo to next message
Chris Delahunt is currently offline Chris DelahuntFriend
Messages: 1389
Registered: July 2009
Senior Member
Can you provide more information, such as the relationships between B, C and D as well as the version you are using? Does it also remove the C object and attempt to reinsert C and D? Does this happen on a flush, and if so, can you try flushing again to see if it finds C/D reattached to the managed object tree?

Re: Sporadic and arbitrary DELETES issued by EclipseLink [message #1044155 is a reply to message #1044068] Thu, 18 April 2013 15:00 Go to previous messageGo to next message
Markus KARG is currently offline Markus KARGFriend
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 Go to previous messageGo to next message
Chris Delahunt is currently offline Chris DelahuntFriend
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


icon9.gif  Re: Sporadic and arbitrary DELETES issued by EclipseLink [message #1044678 is a reply to message #1044187] Fri, 19 April 2013 07:44 Go to previous messageGo to next message
Markus KARG is currently offline Markus KARGFriend
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 #1044888 is a reply to message #1044678] Fri, 19 April 2013 13:13 Go to previous messageGo to next message
Chris Delahunt is currently offline Chris DelahuntFriend
Messages: 1389
Registered: July 2009
Senior Member
Orphan removal requires the deletion of the referenced object when it is dereferenced. This is a spec requirement, which is why it is a bad idea to use it on entities you might wish to have still exist after they are dereferenced. The fact that it works some of the time as you expect I believe I've already explained - the order the tree is traversed determines if it happens one way or the other. That is the problem with your model and relying on two conflicting settings for the same entity.

If you wish to file an enhancement to have the behavior set the way you expect, please do so as others might find it useful as well.
Re: Sporadic and arbitrary DELETES issued by EclipseLink [message #1044939 is a reply to message #1044888] Fri, 19 April 2013 14:34 Go to previous messageGo to next message
Markus KARG is currently offline Markus KARGFriend
Messages: 28
Registered: June 2011
Junior Member
I think there is a misunderstanding. An orphan is an unreferenced object, not a dereferenced-and-again-referenced-in-same-tx object (if you sell your car to me, the car will not vanish. It just changes the "owner" handle; it still is the same car, and neither you nor me are gone; no need for delete-and-insert). So in fact there is no orphan to remove here.

We only *replace* the parent reference and if EclipseLink is designed in a way which does prevent it from correctly deal with that, this is a severe bug.

I will file a bug report for this and ask the spec lead for clarification of this, so we all share the same vision of what an orphan actually is. I do not believe that it is wanted behaviour that the RI sporadically loses rows.

This is neither a problem of my model and conflicting settings, but it is solely a problem of EclipseLink deleteing entities which are *no* Orphans. Actually I cannot see why you think that one shall be an orphan? Which one? Which entity has no parent? The fact that one has no parent is not in our model. It is solely made an Orphan due to EclipseLink's particular implementation, which simply is a design fault.

So still my question is: Our application uploads a valid and consistent entity tree in one single step. This is a business constant. How to fix that without Fixing EclipseLink? Your solutions do not fix this. So what to do now?

Do you really want to say that the solution is that we must prevent users to upload valid entity trees and instead force them to first upload a version where an orphan is synthetically created, and then upload version where the same entity recreates again from scratch at a different place?

Thanks!
-Markus
Re: Sporadic and arbitrary DELETES issued by EclipseLink [message #1044961 is a reply to message #1044939] Fri, 19 April 2013 15:09 Go to previous messageGo to next message
Chris Delahunt is currently offline Chris DelahuntFriend
Messages: 1389
Registered: July 2009
Senior Member
Bug or feature, it remains that you cannot de-reference an object referenced through a relation marked as private owned/orphan removal without causing a delete. The fact the object can be resurrected through a cascade persist/merge relationship is what is causing your issue - you have two conflicting settings. The specification is quite clear, as section 2.9 of the 2.1 spec states regarding orphan removal:
"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 relationship collection), the remove operation
will be applied to the entity being orphaned. The remove operation is applied at the time of
the flush operation. The orphanRemoval functionality is intended for entities that are privately
"owned" by their parent entity. 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. If the entity being orphaned is a detached, new,
or removed entity, the semantics of orphanRemoval do not apply."

So the specification does not allow for it to be reassigned. It is privately owned, and as such is dependent upon its parent for its existence. It is not appropriate for a car that can exist without its owner.
Re: Sporadic and arbitrary DELETES issued by EclipseLink [message #1044969 is a reply to message #1044961] Fri, 19 April 2013 15:17 Go to previous messageGo to next message
Markus KARG is currently offline Markus KARGFriend
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 Go to previous messageGo to next message
Chris Delahunt is currently offline Chris DelahuntFriend
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 #1045051 is a reply to message #1045042] Fri, 19 April 2013 17:49 Go to previous messageGo to next message
Chris Delahunt is currently offline Chris DelahuntFriend
Messages: 1389
Registered: July 2009
Senior Member
Please note that I am not saying there aren't other ways to accomplish what you are after. I've been trying to explain to you that the application relying on being able to reassign private owned objects is not covered by the JPA spec, and never supported by EclipseLink. By all means file an enhancement to have EclipseLink to add support, as it could be a useful feature. EclipseLink arbitrarily calling "delete FROM Table WHERE parent is NULL" is probably a bad idea though - orphan removal means the reference entity is dependent on its parent. Entities can still exist without a parent, or an aggregate/embeddable object should be used instead.

If you want parts of a tree trimmed and deleted from the database, the best option is to provide a mechanism to call em.remove on that part of the tree. If that is not possible, you will need to add in logic to C in say a preUpdate event so that if its parent is set to null, it can call em.remove.

Re: Sporadic and arbitrary DELETES issued by EclipseLink [message #1045443 is a reply to message #1045042] Sat, 20 April 2013 08:43 Go to previous messageGo to next message
Markus KARG is currently offline Markus KARGFriend
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. Smile

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
Re: Sporadic and arbitrary DELETES issued by EclipseLink [message #1045472 is a reply to message #1045443] Sat, 20 April 2013 09:45 Go to previous messageGo to next message
Markus KARG is currently offline Markus KARGFriend
Messages: 28
Registered: June 2011
Junior Member
Chris,

I registered the case in Bugzilla https://bugs.eclipse.org/bugs/show_bug.cgi?id=406144 Smile

Regards
-Markus
Re: Sporadic and arbitrary DELETES issued by EclipseLink [message #1045511 is a reply to message #1045051] Sat, 20 April 2013 11:14 Go to previous message
Markus KARG is currently offline Markus KARGFriend
Messages: 28
Registered: June 2011
Junior Member
Chris,

took the time to think about your idea with the preUpdate listener and I think this will not work in EJB. To remove the orphan within the preUpdate listener, we would need access to the EntitiyManager. But we do not see how to get that? I mean, how to obtain an entity manager instance within a entity? See, we operate in the EJB eco system, so we normally would let it get injected. But injection of EntityManager is part of the next (not current) JPA release.

So how does that solution work like? Maybe we missed some simple but essential Point?

Regards
-Markus
Previous Topic:Predeployment failing on EclipseLink 2.3.2
Next Topic:Value of Column is null while Deleting in ManyToMany-Relationship
Goto Forum:
  


Current Time: Fri Mar 29 07:01:05 GMT 2024

Powered by FUDForum. Page generated in 0.03788 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top