Makes complete sense... I've tested your suggestion and OpenJPA works as
expected.

Anyway, it's weird that if you encapsulate the save/merge code in a DAO,
you have to return the new attached object.

It somehow invades the rest of the code, which is, well... ugly :), IMHO
of course.

Anyway, thanks a lot for all your time and help.

Regards,
Esteve

En/na David Ezzio ha escrit:
> Monday, September 24, 2007
>
> Hi Esteve,
>
> I've taken a look at the test case that you made available. I've
> reproduced the behavior that you are reporting. I can tell you where
> the problem lies, and I've attached code for you that does what your
> test case wants to do and works as expected.
>
> So what's the problem in your test code?
>
> In JPA, the basic life cycle of entities involves four states: new,
> managed, detached, or removed. Entities become detached under the
> following conditions (from the JPA spec):
>
> "3.2.4 Detached Entities
>
> "A detached entity may result from transaction commit if a
> transaction-scoped container-managed entity manager is used (see
> section 3.3); from transaction rollback (see section 3.3.2); from
> clearing the persistence context; from closing an entity manager; and
> from serializing an entity or otherwise passing an entity by
> value—e.g., to a separate application tier, through a remote
> interface, etc."
>
> Therefore, closing the entity manager, when the persistence context
> has extended scope (the default for J2SE), causes the managed entities
> to become detached.
>
> In your example, you create a new Parent in the runTest1 method, make
> it persistent (managed), and put it in a map. You then close the
> entity manager. Viola! The parent stored in the map under "OBJ" tag
> has become detached.
>
> In the next method, runTest2, you take this Parent and add two new
> children to it. The two children are new. They are not managed. You
> merge this object keeping the original detached object in the map. You
> close the entity manager. Result, 2 new children added to the
> database, in a one-to-many relationship to the Parent. BUT, the Parent
> in the map, although still detached, still has two new (not detached
> nor managed) children.
>
> In the next method, runTest3, you take the original Parent, and add
> two more new children to it. You then merge the detached Parent again.
> Result, four more new children added to the database, which the Parent
> has a one-to-many relationship to, but the the Parent "forgets" about
> the relationship to the two children (still in the database) added in
> runTest2.
>
> The problem is that when you merge, you get back from the merge
> method, a reference to the resulting managed object. If you take that
> reference and put it in the map, you'll have after commit and the
> closing of the entity manager, a detached reference to a Parent with
> two detached (NOT NEW) children. Then in step three, when you add two
> more children, you end up with just four children in the database,
> with no forgetten children.
>
> If you had put a version column in the Parent, I believe it would have
> caught the duplicate use of the same detached version of the Parent
> and thrown an OptimisticLockException in runTest3 since that version
> had already been merged and committed with changes once before in
> runTest2.
>
> Make sense?
>
> Cheers,
>
> David
>
>   

Reply via email to