openjpa-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Henno Vermeulen <>
Subject RE: How to add children to disconnected entity?
Date Thu, 27 Sep 2012 08:27:02 GMT

Not sure I exactly understand the situation. Perhaps you are using cascade merge on both of
the objects that refer to it?
Normally you shouldn't use cascade merge when it is only an association and use cascade merge
when the entity really "owns" the other entity.

Suppose A and B both refer to C (A -> C, B -> C) and C is owned by A.
Then the relation A -> C should use cascade merge but B -> C should not.
If C is an existing entity and you merge A, C will be merged as well. If you then merge B
which refers to the same C, this should succeed even if the version of C contained in B is
an old one. The relation B -> C does not use cascade merge so when merging B only the identity
of C matters. (If it would cascade merge you would get an optimistic lock exception if you
use that or otherwise you could overwrite C with old data).

Perhaps you are in the situation where you are using id generated by OpenJPA and C is not
yet persisted. I always regard two objects that are not persistent but have exactly the same
data to be different from each other. The reason is that the act of merging does not change
the parameter to merge. Instead it returns an attached object which represents the same logical
entity in the database but does not refer to the same object in memory. I always regard merge
as a save operation that does not change the parameter so I throw away the entity passed-in
and work with the retuned one. I always take care to first merge an unpersisted entity before
I use it in an associaton with another entity.

Detailed explanation of what happens: when B refers to a "clone" of the unpersisted C there
is absolutely no way for OpenJPA to recognize that B has a reference to the same C as A has.
Suppose you start out with an A and B referring to the same unpersisted C in memory. You then
merge A and this cascade merges C. The result of the merge operation will contain a now persistent
copy of C but the original unpersisted C object in memory is not changed, i.e. the C that
results from the merge refers to another object in memory. If you then merge B you should
get an exception that the relation does not allow cascade because B still refers to the unpersisted
C. However if the relation B -> C was set to cascade merge, then you will end up with B
referring to another new instance that has the same data as C but does not have the same database

Hope this explanation helps, even though it may not be your exact situation. The moral of
the story that I learned over time is to realize that merge does not alter its parameter so
that you should really regard two unpersisted clones as different. And it's usually better
to use cascade merge only on one relation, i.e. from it's owner to the entity. This will prevent
the bugs that you can silently get a duplicate or merge an older version.

-----Oorspronkelijk bericht-----
Van: Jim Talbut [] 
Verzonden: woensdag 26 september 2012 23:05
Onderwerp: Re: How to add children to disconnected entity?

On 26/09/2012 10:57, Jim Talbut wrote:
> On 26/09/2012 10:19, Henno Vermeulen wrote:
>> Hi,
>> I verified this situation by making an extra unit test in our system. 
>> We always work with detached entities as well. The test works fine 
>> for me.
>> One explanation for this behavior is that the @OneToMany field does 
>> not use "fetch = FetchType.EAGER" because relations are lazily 
>> fetched by default. (Or alternatively you have not included the field 
>> in OpenJPA's FetchPlan before calling entityManager.merge which has 
>> the same effect as FetchType.EAGER even if the @OneToMany field is 
>> not eager).
>> When I adjust my test to lazily fetch the field, then saving a new 
>> Assessment somehow DOES cascade merge new AssessmentResults. However 
>> when I merge an existing Assessment that has one existing 
>> AssessmentResult and one new AssessmentResult, OpenJPA will not 
>> cascade merge it.
> Thank you.
> Yes, that is precisely what I'm going to be doing.
> The results are large, so they are Lazy loaded, and the assessments 
> are created in a different transaction - so the list is always empty 
> when first loaded.
> What I'm doing at the moment is, in the function that calls merge, 
> iterating through the results and persisting any that aren't contained 
> or detached.
> I have to do that first (before merging the assessment) or some 
> results get persisted twice.
> This seems to be working (well, one of my unit tests passed, I've got 
> other unit tests failing and that may not be related to this).
> Jim

I've got that nearly all working now, but I've still got one big problem.

The detached entity that I create has two objects referring to it: one 
of which gets merged and the other gets persisted.
The act of merging attaches the new entity, but replaces the variable 
the refers to it.
So when the other entity gets persisted I end up with a duplicate entity.

This is all caused by trying to break down big transactions into much 
smaller ones, which is why it's not the best structure.


View raw message