Does the JPA optimistic locking specification support validating against a version supplied by a client

夙愿已清 提交于 2020-01-06 02:41:25

问题


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?


回答1:


Eeeek, externally setting the @Version field? This would probably lead in most cases to conflicts, as it is not supposed to be set by the developer. It is managed by the Persistence Provider, exclusively. You won't need a getter nor a setter to access the version.

An excerpt from the JPA 2.0 spec:

The Version field or property is used by the persistence provider to perform optimistic locking. It is accessed and/or set by the persistence provider in the course of performing lifecycle operations on the entity instance. An entity is automatically enabled for optimistic locking if it has a property or field mapped with a Version mapping. An entity may access the state of its version field or property or export a method for use by the application to access the version, but must not modify the version value[34]. With the exception noted in section 4.10, only the persistence provider is permitted to set or update the value of the version attribute in the object.

Regarding your update process: You typically retrieve the ID of your object and the data you want to change from your Rest Interface. You pass both to a Service, in which you tell your EntityManager to fetch the entity with the given ID, update the data on that entity, and tell the EntityManager to save it back right away. This procedure is not carved in stone, but roughly that's how it's done in most cases.

Both, the setID() and setVersion() methods on your entites are very likely to be bad practice.



来源:https://stackoverflow.com/questions/50420000/does-the-jpa-optimistic-locking-specification-support-validating-against-a-versi

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!