Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [eclipselink-users] merge() cascading by default?

I filed https://bugs.eclipse.org/bugs/show_bug.cgi?id=247662 but it looks
like I might have jumped to conclusions (i.e. this behavior could be outside
the JPA specification).

Here is what the TopLink documentation says:

http://www.oracle.com/technology/products/ias/toplink/jpa/resources/toplink-jpa-annotations.html
reads "By default, TopLink JPA does not cascade any persistence operations
to the target of the association." and it goes on to list "merge" as a
possible type of cascade, which behaves with the behavior we're seeing.

So at the very least, we seem to have a bug with respect to the TopLink
documentation.

Now things get interesting... The JPA specification reads:

"3.2.4.1 Merging Detached Entity State

If X is a new entity instance, a new managed entity instance X' is created
and the state of X is
copied into the new managed entity instance X'.

If X is an entity merged to X', with a reference to another entity Y, where
cascade=MERGE or cascade=ALL is not specified, then navigation of the same
association from X' yields a reference to a managed object Y' with the same
persistent identity as Y."

I believe the first paragraph is talking about new entities while the second
paragraph is talking about persistent entities. The first paragraph doesn't
say what happens if the new entity has associations and the second paragraph
doesn't say what happens for new entities so my guess is that this situation
is not explicitly covered by this section.

Still, if you read other sections of the specification, they say the default
cascade is none and "the semantics of the flush operation" in section "3.2.3
Synchronization to the Database" reads:

"For any entity Y referenced by a relationship from X, where the
relationship to Y has
not been annotated with the cascade element value cascade=PERSIST or
cascade=ALL:

• If Y is new or removed, an IllegalStateException will be thrown by
the flush operation (and the transaction rolled back) or the transaction
commit
will fail."

By extension, I believe it is fair to assume that the same behavior is
expected for merge(), but you be the judge :)

Thanks,
Gili


James Sutherland wrote:
> 
> It looks like for new objects they will just be registered entirely
> (persistence by reachablity/cascade all).  I'm not sure what the JPA spec
> says on this, as merge() is different than persist(), but it is probably
> worth logging a bug in EclipseLink to have this scenario reviewed.
> 
> Either way you are going to get an error, so best to fix your object that
> you are merging.
> 
> 
> 
> cowwoc wrote:
>> 
>> Hi James,
>> 
>> I am merging a new object where all its attributes are new, however when
>> it goes to merge() the entity to disk I know for a fact the specification
>> attribute already exists (which is why you see the insertion failure). I
>> understand what you said about merging an instance and skipping any
>> non-cascade attributes but I would expect the following operation to
>> fail:
>> 
>> 1) The entity being merged is new
>> 2) One of the attributes points to a new entity but does not have cascade
>> enabled
>> 
>> because clearly then you're trying to persist an incomplete object. The
>> counter-example is if you're merging an existing entity. I agree that in
>> such a case it should skip merging any attribute with cascade disabled
>> (so long as the attribute is already persisted, if the attribute is new
>> then I expect a failure).
>> 
>> Please confirm whether you agree with the above statements or which ones
>> I have misunderstood. As for my specific use-case, I have class Image
>> with attribute Specification (which you see getting inserted). The
>> attribute is declared with the following annotations:
>> 
>> 	@ManyToOne(optional = false, fetch = FetchType.LAZY)
>> 	@JoinColumn(name = "specificationId")
>> 
>> Gili
>> 
>> 
>> James Sutherland wrote:
>>> 
>>> I think this is correct.
>>> 
>>> merge() and persist() are different operations.  Merge is merging from
>>> one detached copy of the object, into a managed object, if something is
>>> not cascade merge, it just doesn't need to merge that attribute.  For
>>> persist the new object is being made managed (itself, not a copy), so
>>> has to resolve all of its references.
>>> 
>>> However, I would expect the relation to just not be merged, not to be
>>> inserted.  Is the object you are merging new or existing?  How are the
>>> new object relations that are inserted mapped?  Perhaps include some
>>> example code.
>>> 
>>> 
>>> 
>>> cowwoc wrote:
>>>> 
>>>> Here is the output I see with logging enabled.
>>>> 
>>>> I hope file attachments works with nabble :)
>>>> good.txt refers to the output I expect. bad.txt refers to the
>>>> unexpected cascade.
>>>> 
>>>>  http://www.nabble.com/file/p19501990/good.txt good.txt 
>>>>  http://www.nabble.com/file/p19501990/bad.txt bad.txt 
>>>> 
>>>> Gili
>>>> 
>>>> 
>>>> cowwoc wrote:
>>>>> 
>>>>> When I merge() an Image object, EclipseLink seems to persist all
>>>>> objects referenced by the object. If I change to persist() it
>>>>> complains that one of the referenced object was transient but not
>>>>> cascaded.
>>>>> 
>>>>> I am expecting the same warning to be issued for merge(). The
>>>>> documentation says that the default cascade is none but the behavior
>>>>> seems otherwise. I am using EclipseLink 1.0.1.
>>>>> 
>>>>> Thank you,
>>>>> Gili
>>>>> 
>>>> 
>>>> 
>>> 
>>> 
>> 
>> 
> 
> 

-- 
View this message in context: http://www.nabble.com/merge%28%29-cascading-by-default--tp19501823p19534533.html
Sent from the EclipseLink - Users mailing list archive at Nabble.com.



Back to the top