|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: "22.214.171.124 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