Suppose I have an entity defined as follows:
@Entity
public class MyEntity {
@Id
@GeneratedValue
private Integer id;
@Column
private String name;
@Version
int version;
// Getters + setters
}
Suppose also I have a service (REST API or something similar) that allows a user to retrieve information about this entity. It returns the ID, the current name, and the current version. There is also another service that allows a user to update the name of an entity. It accepts the ID, update name, and version as input parameters. So the entity could be updated by creating a new object and using a merge:
public MyEntity update(EntityManager em, int id, String name, int version) {
MyEntity entity = new Entity();
entity.setId(id);
entity.setName(name);
entity.setVersion(version);
return em.merge(entity);
}
Alternatively it could be updated by retrieving it from the database and updating the relevant fields only:
public MyEntity update(EntityManager em, int id, String name, int version) {
MyEntity entity = em.find(MyEntity.class, id);
entity.setName(name);
entity.setVersion(version);
return entity;
}
My testing tells me that in Hibernate 5.3 the first scenario will throw an OptimisticLockException (with the message Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect)
) if the provided version does not match what is in the database. However, the second scenario works fine and the name is updated regardless of the version supplied.
I have also tried this with DataNucleus 5.1.9 and there neither scenario throws an exception and the name is updated regardless of the version supplied in both cases.
So I guess either there is a bug in Hibernate or DataNucleus, one of them is not following the JPA specification, or the specification doesn't clearly specify how this should work?
I have tried to find a definitive answer to this but was unable to do so. Can someone confirm how, according to the JPA specification, should optimistic locking work when it comes to updating entities with a version number supplied externally?