JPA @EmbeddedId: How to update part of a composite primary key?

composite-primary-key, embedding, jpa, optimistic-locking

Solution

Why not just change the primary key of `Composition` to be a UID which is auto-generated? Then the users could change the two references to the entities being joined without having to delete/re-create the `Composition` entity. Optimistic locking would then be maintained.

EDIT: For example:

@Entity
@Table(name = "COMPOSITION")
public class Composition {

    @Id
    @Column(name = "ID")
    private Long id;   // Auto-generate using preferred method

    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumn( .... as appropriate .... )
    private FirstEntity firstEntity;

    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumn( .... as appropriate .... )
    private SecondEntity secondEntity;

....

Problem

I have a many-to-many relationship where the link table has an additional property. Hence the link table is represented by an entity class too and called `Composition`. The primary key of `Composition` is an `@Embeddable` linking to the according entities, eg. 2 `@ManyToOne` references. It can happen that a user makes an error when selecting either of the 2 references and hence the composite primary key must be updated. However due to how JPA (hibernate) works this will of course always create a new row (insert) instead of an update and the old `Composition` will still exist. The end result being that a new row was added instead of one being updated. Option 1: The old `Composition` could just be deleted before the new one is inserted but that would require that the according method handling this requires both the old and new version. plus since the updated version is actually a new entity optimistic locking will not work and hence last update will always win. Option 2: Native query. The query also increments version column and includes version in WHERE clause. Throw `OptimisticLockException` if update count is 0 (concurrent modification or deletion) What is the better choice? What is the "common approach" to this issue?

Original source