merge of a deleted object results in a insert?

Description

A persistent object is loaded from a session and deleted, then close the session. Using that same object in another session and call merge results in the object being inserted into the database. Here's the sample code:

Since the object is already deleted, merge could not find it and thus proceeds with a INSERT. Shouldn't it throw an exception instead?

Attachments

1

Activity

Show:

Gavin King May 21, 2024 at 7:29 PM

Fixed, finally. Note that this issue was first reported as by Bill Burke himself in 2005.

Nineteen years ago.

Gavin King May 21, 2024 at 3:27 PM

This is fixed by .

However, I’m wondering, giving its breaking nature, if we should target H7 instead of 6.6.

Gavin King May 21, 2024 at 10:42 AM
Edited

There’s confusion about the removed state in the JPA entity lifecycle model in this discussion. At first I was surprised by this, because the spec itself appears to be quite explicit:

  • A removed entity instance is an instance with a persistent identity, associated with a persistence context, that will be removed from the database upon transaction commit.

That is, for an entity to be in the removed state, it must be associated with a persistence context. After the persistence context is closed, it is no longer considered removed.

But looking more closely, I notice that the spec is not explicit about the following:

  1. Section 3.3.4 does not say whether the entity remains in the removed state after the SQL delete has been performed.

  2. Section 3.3.7 does not say that removed (and deleted) entities become detached when the persistence context is destroyed. Section 3.3.6 would lead one to imagine that this is the intent, but it’s not explicit.

In Hibernate we resolve 1 by actually having a GONE state for entities which have been deleted from the database. And that’s completely fine.

Now, 2 raises a much more difficult problem, which is that in some cases we simply can’t tell if an object is new or detached. This is the case for entities with no @Version and an assigned identifier. The best we can do here is just assume they are new, and let you re-persist them. [This issue is, I suppose, the real reason the spec goes all vague on this point.]

However, in the cases where:

  • the entity has a generated id, or

  • a nonzero version,

then we can determine for sure whether the entity is detached, and have two choices of how to treat that object in persist():

  1. We could do what I think is probably the most faithful thing from the point of view of what the spec does say, which is treat it as detached and refuse to re-persist it.

  2. Alternatively, we could be consistent with what happens for the cases where we cannot tell, which is treat it as new, and persist it with a brand new generated id and a reset version number.

Either of these behaviors is defensible. There’s nothing intrinsically wrong and crazy with the notion of re-persisting a removed entity!

The issue, however, arises with merge()when:

  1. TX1 reads an instance,

  2. TX2 deletes it,

  3. TX1 attempts to merge() an update, and ends up re-persisting the deleted object.

This should clearly result in an optimistic lock failure, at least in the case of a versioned entity. I think that’s at least approximately what is trying to do, but the proposed fix is not quite perfect. On the other hand, doesn’t look correct at all.

Steve Ebersole July 17, 2023 at 4:43 PM

Is “current Session” the same throughout?

Steve Ebersole July 17, 2023 at 4:07 PM

Perhaps I am misunderstanding here, but after the first call above to session.getTransaction().commit(); the entity is not detached. Detached indicates there is a corresponding row in the database, which is not the case here. What am I missing?

If X is a removed entity instance, an IllegalArgumentException will be thrown by the
merge operation (or the transaction commit will fail).

That is talking about the removed status, which is true before the flush+commit. After the commit, the entity is gone.

Fixed

Details

Assignee

Reporter

Labels

Components

Sprint

Fix versions

Affects versions

Priority

Created April 11, 2006 at 6:33 PM
Updated June 14, 2024 at 3:08 PM
Resolved May 21, 2024 at 7:29 PM