Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
RE: [eclipselink-users] Looks like Hibernate design bug about resurrecting deleted object contaminated JPA, so EclipseLink

Sebastien,

The EJB 3.0 (JPA 1.0) expert group decided on this approach to cascading PERSIST, MERGE, REMOVE operations instead of persistence by reachability. I bump into this issue as well working with JPA and it does require some additional attention if you are used to the way EclipseLink's native UnitOfWork approach worked. I would not call it a bug though as the specification clearly intended this behaviour.

If you would like this behaviour with EclipseLink JPA then you can either use the native UnitOfWork directly or we can investigate an additional flag to allow the EntityManager to work in a 'reachability' mode. We would need to discuss and investigate this a bit. I would recommend opening an enhancement request to get the ball rolling.

BTW: Have you looked at the new unidirectional 1:M support added in EclipseLink 1.1. It may address your bi-directional issues.

Doug

-----Original Message-----
From: Sebastien Tardif [mailto:stardif@xxxxxxxxxxxx]
Sent: Tuesday, June 30, 2009 4:52 PM
To: EclipseLink User Discussions
Subject: [eclipselink-users] Looks like Hibernate design bug about
resurrecting deleted object contaminated JPA, so EclipseLink


Looks like Hibernate design bug about resurrecting deleted object
contaminated JPA, so EclipseLink.

I have a complex application that is originally based on
TopLink/EclipseLink native API. I mean by "complex" an application where
it is unrealistic to babysit every use case, or code path to put
workaround to fix thorny framework.

In native EclipseLink, the functionality of persistence by reachability
was simpler and likely the right thing. Any object that was reachable
was persisted. So if I had a chick and a roster having bidirectional
relationship I could just register any one of them and the other would
have been persisted.

Also if I would have deleted explicitly one of them without setting
existing reference to null, then in the next UOW I would have found null
in the reference pointing to the deleted animal, a reasonable default.

Now in JPA:

I use the hook in persistence.xml to use native EclipseLink mapping. The
mapping is imported but defaulting with no cascade of any kind. I then
fix the wrong default by setting cascade persist everywhere, and cascade
delete to all private owned relationships, matching the native behavior.

Then my complex application start to break with simple use case doing
deletion. I can simplify the broken use case to this:
1- Read X, X has one child having bidirectional relationship
2- Delete X EXPLICITLY
3- Commit

Then X is not deleted! My explicit wish have been overridden by some
weird implicit feature.

Remember, I have a complex application, not a lab test case used by some
specification writer. Now, if I babysit all my hundreds of references to
remove cascade persist from child to parent, existing code that was
working fine by just explicitly register the child will be broken.

EclipseLink one-to-many requires back reference to parent, so I have
been pushed to have more bidirectionality than what I wished for.

Also it's not always child to parent relationship that will trigger
resurrection. I likely have in my old application extra reference to the
deleted object that have not been nullified.

Maybe because Oracle is a big company, I was expecting they provide way
for backward compatibility. However, no flag exist to void the JPA
design bug.

You can see below that some Oracle developer agree that this design bug
is not the right thing:

Extract from
http://fisheye2.atlassian.com/browse/~raw,r=4388/eclipselink/trunk/found
ation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/
sessions/UnitOfWorkImpl.java:

public void discoverAndPersistUnregisteredNewObjects(Object object,
boolean cascadePersist, Map newObjects, Map unregisteredExistingObjects,
Map visitedObjects) {
        if (object == null) {
            return;
        }
        
        if (cascadePersist && isObjectDeleted(object)) {
            // It is deleted but reference by a cascade persist mapping,
spec seems to state it should be undeleted, but seems wrong.
            // TODO: Reconsider this.
            undeleteObject(object);
        }

Someone could think that I should be able to find a hook to override the
method discoverAndPersistUnregisteredNewObjects, but concrete class is
hardcoded in EntityManagerImpl.java:

public RepeatableWriteUnitOfWork getActivePersistenceContext(Object txn)
{
        // use local uow as it will be local to this EM and not on the
txn
        if (this.extendedPersistenceContext == null ||
!this.extendedPersistenceContext.isActive()) {
            this.extendedPersistenceContext = new
RepeatableWriteUnitOfWork(this.serverSession.acquireClientSession(connec
tionPolicy, properties), this.referenceMode);
 
this.extendedPersistenceContext.setResumeUnitOfWorkOnTransactionCompleti
on(!this.closeOnCommit);
 
this.extendedPersistenceContext.setShouldDiscoverNewObjects(this.persist
OnCommit);
 
this.extendedPersistenceContext.setFlushClearCache(this.flushClearCache)
;
 
this.extendedPersistenceContext.setShouldValidateExistence(this.shouldVa
lidateExistence);
 
this.extendedPersistenceContext.setShouldCascadeCloneToJoinedRelationshi
p(true);
_______________________________________________
eclipselink-users mailing list
eclipselink-users@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/eclipselink-users


Back to the top