Home » Eclipse Projects » EclipseLink » 1.1.3 vs 2.0 equals
1.1.3 vs 2.0 equals [message #501455] |
Wed, 02 December 2009 07:05  |
Eclipse User |
|
|
|
I have a @PrePersist on the child entities of a master-detail relation. In the @PrePersist is some checking done against the other childeren in the same master-detail relation.
At runetime, the child object that is executing the @PrePersist is actually a clone of an the object that is in the master-detail collection. So I need to use equals to determine if this is the same object.
if (!this.equals(lOther)) ...
The equals method includes the @Id and and @Version fields in the compare.
When running against 1.1.3 the cloned object does NOT yet have its @Id and @Version set, all four values are null.
When running against 2.0.0RC1 the cloned object DOES have its @Id and @Version set.
So equals behavior is not identical between 1.1.3 and 2.0.0RC1.
Is this change intentional?
Tom
|
|
| | | |
Re: 1.1.3 vs 2.0 equals [message #502223 is a reply to message #501741] |
Mon, 07 December 2009 04:44   |
Eclipse User |
|
|
|
This is the simplified code in the Address child class. I inserted a println to show the hashcode of the compared entities.
@PrePersist @PreMerge
public void preSaveHook()
{
for (Address lAddress : getRelation().getAddressesWhereIAmRelation())
{
System.out.println( this.hashCode() + " vs " + lAddress.hashCode() );
if (!this.equals(lAddress))
{
...
}
}
}
There is one relation (master) with one new address (child), the relation is merged and the address is cascade persisted. This is the output:
17440602 vs 30741250
The compare happens between two different objects, both of class Address. If this is examined in debug mode all properties are identical, except:
- the "other" has a value for the @Id and @Version field, while for "this" these are null
- the "other" has no values for the relation property.
As mention in a previous post, in 1.1.3 this was different; neither the clone nor the original had @Id or @Version values and both had all fields set.
This is the stackstace, what seems important here is the method "registerNewObjectClone":
Thread [AWT-EventQueue-0] (Suspended)
Address.preSaveHook() line: 47
Address(AbstractBean<T>).prePersist() line: 250
NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]
NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39
DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25
Method.invoke(Object, Object...) line: 597
PrivilegedAccessHelper.invokeMethod(Method, Object, Object[]) line: 346
EntityClassListener(EntityListener).invokeMethod(Method, Object, Object[], DescriptorEvent) line: 297
EntityClassListener.invokeMethod(String, DescriptorEvent) line: 64
EntityClassListener(EntityListener).prePersist(DescriptorEve nt) line: 399
DescriptorEventManager.notifyListener(DescriptorEventListene r, DescriptorEvent) line: 670
DescriptorEventManager.notifyEJB30Listeners(DescriptorEvent) line: 606
DescriptorEventManager.executeEvent(DescriptorEvent) line: 200
RepeatableWriteUnitOfWork(UnitOfWorkImpl).registerNewObjectC lone(Object, Object, ClassDescriptor) line: 4237
RepeatableWriteUnitOfWork.cloneAndRegisterNewObject(Object) line: 507
RepeatableWriteUnitOfWork(UnitOfWorkImpl).internalRegisterOb ject(Object, ClassDescriptor) line: 2902
RepeatableWriteUnitOfWork(UnitOfWorkImpl).registerObject(Obj ect, ClassDescriptor) line: 4326
RepeatableWriteUnitOfWork(UnitOfWorkImpl).registerObject(Obj ect) line: 4284
OneToManyMapping(CollectionMapping).buildElementClone(Object , Object, UnitOfWorkImpl, boolean) line: 242
IndirectListContainerPolicy(ContainerPolicy).addNextValueFro mIteratorInto(Object, Object, Object, CollectionMapping, UnitOfWorkImpl, boolean) line: 264
OneToManyMapping(CollectionMapping).buildCloneForPartObject( Object, Object, Object, UnitOfWorkImpl, boolean) line: 195
TransparentIndirectionPolicy.cloneAttribute(Object, Object, Object, UnitOfWorkImpl, boolean) line: 148
OneToManyMapping(ForeignReferenceMapping).buildClone(Object, Object, UnitOfWorkImpl) line: 172
ObjectBuilder.populateAttributesForClone(Object, Object, UnitOfWorkImpl) line: 2690
RepeatableWriteUnitOfWork.cloneAndRegisterNewObject(Object) line: 502
RepeatableWriteUnitOfWork(UnitOfWorkImpl).internalRegisterOb ject(Object, ClassDescriptor) line: 2902
MergeManager.registerObjectForMergeCloneIntoWorkingCopy(Obje ct) line: 841
MergeManager.mergeChangesOfCloneIntoWorkingCopy(Object) line: 473
MergeManager.mergeChanges(Object, ObjectChangeSet) line: 267
RepeatableWriteUnitOfWork(UnitOfWorkImpl).mergeCloneWithRefe rences(Object, MergeManager) line: 3486
RepeatableWriteUnitOfWork.mergeCloneWithReferences(Object, MergeManager) line: 301
RepeatableWriteUnitOfWork(UnitOfWorkImpl).mergeCloneWithRefe rences(Object, int, boolean) line: 3446
EntityManagerImpl.mergeInternal(Object) line: 414
EntityManagerImpl.merge(T) line: 391
NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]
NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39
DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25
Method.invoke(Object, Object...) line: 597
EclipselinkEntityManagerExtender(EntityManagerExtender).invo ke(Object, Method, Object[]) line: 124
$Proxy3.merge(Object) line: not available
JpaObjectNavigatorModel$1.call() line: 812
JpaObjectNavigatorModel<T>.doSave() line: 825
JpaObjectNavigatorBar$4.actionPerformed(ActionEvent) line: 157
JButton(AbstractButton).fireActionPerformed(ActionEvent) line: 1995
AbstractButton$Handler.actionPerformed(ActionEvent) line: 2318
DefaultButtonModel.fireActionPerformed(ActionEvent) line: 387
DefaultButtonModel.setPressed(boolean) line: 242
BasicButtonListener.mouseReleased(MouseEvent) line: 236
AWTEventMulticaster.mouseReleased(MouseEvent) line: 272
JButton(Component).processMouseEvent(MouseEvent) line: 6263
JButton(JComponent).processMouseEvent(MouseEvent) line: 3267
JButton(Component).processEvent(AWTEvent) line: 6028
JButton(Container).processEvent(AWTEvent) line: 2041
JButton(Component).dispatchEventImpl(AWTEvent) line: 4630
JButton(Container).dispatchEventImpl(AWTEvent) line: 2099
JButton(Component).dispatchEvent(AWTEvent) line: 4460
LightweightDispatcher.retargetMouseEvent(Component, int, MouseEvent) line: 4574
LightweightDispatcher.processMouseEvent(MouseEvent) line: 4238
LightweightDispatcher.dispatchEvent(AWTEvent) line: 4168
JFrame(Container).dispatchEventImpl(AWTEvent) line: 2085
JFrame(Window).dispatchEventImpl(AWTEvent) line: 2478
JFrame(Component).dispatchEvent(AWTEvent) line: 4460
EventQueue.dispatchEvent(AWTEvent) line: 599
EventDispatchThread.pumpOneEventForFilters(int) line: 269
EventDispatchThread.pumpEventsForFilter(int, Conditional, EventFilter) line: 184
EventDispatchThread.pumpEventsForHierarchy(int, Conditional, Component) line: 174
EventDispatchThread.pumpEvents(int, Conditional) line: 169
EventDispatchThread.pumpEvents(Conditional) line: 161
EventDispatchThread.run() line: 122
|
|
| |
Re: 1.1.3 vs 2.0 equals [message #502357 is a reply to message #502302] |
Mon, 07 December 2009 14:05   |
Eclipse User |
|
|
|
James wrote:
> From your stack you are doing a merge() of the master, not a
> persist(). Merge must always create a clone of the objects, and the
> merged object is a clone.
>
> Because the event is fired during the merge process, the state of its
> related objects may undefined, as it is in the processes of merging them.
I do not quite understand this. I have a new entity; it is persisted by relation, why is the action being done on the parent of influence on the action done on my new entity; it is new, it is persisted.
Secondly, in 1.1.3 the behavior was different:
- the @Id and @Version were not set on the clone
- the related entities were set
Why this changed so much? I had to strip down the equals method tremendously (take out both @Id, @Version and any non primary properties) which makes it far less accurate. If the state is undefined, can it please be undefined as it was in 1.1.3? :-)
Tom
|
|
| |
Re: 1.1.3 vs 2.0 equals [message #502730 is a reply to message #502719] |
Wed, 09 December 2009 10:04   |
Eclipse User |
|
|
|
> persist() and merge() are two different operations. persist takes a new
> object and make that instance managed in the persistence context.
>
> merge() is for when you have a detached, or serialized copy of an
> object. You want to merge the changes from your copy, but not effect
> your detached copy in any way. So the new object being merged must
> remain detached, and a copy of it persisted.
Ok. But given the situation where there is a master entity that already existed, so it needs to be merged, but it has a new child entity, which should be persisted...
Am I correct that a good approach could be to never use cascade persist or merge, and explicitly call persist on all objects? In that way the master is merged and the new child is persisted?
> EclipseLink does have other events, depending on what you are doing you
> may wish to look into those, such as the preInsert DescriptorEvent.
All I want is to compare and validate the properties of related entities before persist or merge. I'll take a look.
Tom
|
|
| | | |
new events [message #503037 is a reply to message #502993] |
Thu, 10 December 2009 11:15   |
Eclipse User |
|
|
|
This is the code that I execute:
Relation lRelation = Relation.findByPK(100306); // this is just an EM.find(Relation.class, relationnr);
lRelation.setName(lRelation.getName() + "x");
Address lAddress = lRelation.getAddressesWhereIAmRelation().get(0);
lRelation.removeAddressesWhereIAmRelation(lAddress); // removes from collection and sets relation to null
lEntityManager.remove(lAddress);
lEntityManager.getTransaction().begin();
lEntityManager.merge(lRelation);
lEntityManager.getTransaction().commit();
I see that first an update is executed setting the relationnr to null
setBigDecimal=16034 / UPDATE address SET dwhmodified = ?, dwhby = ?, relationnr = ?, lazylock = ? WHERE ((addressnr = >>>HERE<<< ) AND (lazylock = ?))
setNull=-5 / UPDATE address SET dwhmodified = ?, relationnr = >>>HERE<<< , lazylock = ? WHERE ((addressnr = ?) AND (lazylock = ?))
And then immediately a delete
setBigDecimal=16034 / DELETE FROM address WHERE ((addressnr = >>>HERE<<< ) AND (lazylock = ?))
Why update then delete? There is no cascade merge...
@ManyToOne(fetch = FetchType.LAZY, targetEntity = nl.reinders.bm.Relation.class, cascade = {CascadeType.REFRESH} ) @JoinColumn(name="relationnr")
volatile protected nl.reinders.bm.Relation iRelation;
@OneToMany(mappedBy = "iRelation", fetch = FetchType.LAZY, targetEntity = nl.reinders.bm.Address.class, cascade = {CascadeType.REFRESH,CascadeType.REMOVE} )
volatile protected java.util.List<nl.reinders.bm.Address> iAddressesWhereIAmRelation = new java.util.ArrayList<nl.reinders.bm.Address>();
Tom
|
|
| |
Re: new events [message #503762 is a reply to message #503749] |
Tue, 15 December 2009 11:03  |
Eclipse User |
|
|
|
On 2009-12-15 16:46, James wrote:
> The code is a little odd. Since you appear to be finding the lRelation
> in the same EntityManager, there is no point to calling merge() on it,
> as it is already managed. Also it is somewhat odd to be calling remove()
> before starting the transaction.
Yes. But consider this from a stand alone Swing application point of view; you are updating the entities all around the swing application, but I only start a transaction and manipulate the database when the users presses "save". Until then everything must be done in memory. So that is the reason for the remove-out-side-the-transaction; simulate a user deleting a child (address).
This is also why I have an extended entity manager, which remembers any actions done when no transaction is active, and then re-executes those upon the commit.
> The UPDATE occurs before the DELETE because you are modifying the
> object, if you did not modify it then it would not be updated. Objects
> that are modified are updated before they are deleted because the update
> may be required for database constraints.
Ok. That makes things clear; this is the result of the "setModifiedBy" call I mention in another post.
Tom
|
|
|
Goto Forum:
Current Time: Wed Jul 23 19:38:53 EDT 2025
Powered by FUDForum. Page generated in 0.05508 seconds
|