JPA乐观锁定规范是否支持针对客户端提供的版本进行验证 [英] Does the JPA optimistic locking specification support validating against a version supplied by a client

查看:91
本文介绍了JPA乐观锁定规范是否支持针对客户端提供的版本进行验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个定义如下的实体:

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
}

假设我还有一个服务(REST API或类似的东西),允许用户检索有关此实体的信息.它返回ID,当前名称和当前版本.还有另一项服务,允许用户更新实体的名称.它接受ID,更新名称和版本作为输入参数.因此,可以通过创建新对象并使用合并来更新实体:

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;
}

我的测试告诉我,在Hibernate 5.3中,如果提供的版本与数据库中的版本不匹配,则第一种情况将引发OptimisticLockException(带有消息Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect)).但是,第二种情况都可以正常工作,并且无论提供的版本如何,名称都可以更新.

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.

我还使用DataNucleus 5.1.9进行了尝试,并且无论哪种情况都不会引发异常,并且无论两种情况下提供的版本如何,名称都将被更新.

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.

所以我想Hibernate或DataNucleus中有一个错误,其中之一没有遵循JPA规范,或者该规范没有明确指定应如何工作?

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?

我试图找到一个明确的答案,但未能做到.有人可以根据JPA规范确认在使用外部提供的版本号更新实体时乐观锁定应该如何工作吗?

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?

推荐答案

Eeeeek,在外部设置@Version字段吗?在大多数情况下,这可能会导致冲突,因为开发人员不应该设置冲突.它由持久性提供程序专门管理.您不需要gettersetter即可访问version.

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.

JPA 2.0规范摘录:

An excerpt from the JPA 2.0 spec:

持久性提供程序使用Version字段或属性来 执行乐观锁定.它是由访问和/或设置的 在执行生命周期操作过程中的持久性提供程序 在实体实例上.实体已自动启用 乐观锁定(如果它具有与Version映射的属性或字段) 映射.实体可以访问其版本字段的状态,也可以访问 属性或导出方法以供应用访问 版本,但不得修改版本值[34].有这个特例 在本节中指出 4.10,仅允许持久性提供程序设置或更新对象中version属性的值.

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.

关于更新过程:通常,您可以从休息界面"中检索对象的ID和要更改的数据.两者都传递给Service,在其中告诉EntityManager提取具有给定ID的实体,更新该实体上的数据,然后告诉EntityManager立即将其保存.此过程不是刻在石头上的,但是在大多数情况下,大致都是这样.

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.

在实体上使用setID()setVersion()方法都是很不好的习惯.

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

这篇关于JPA乐观锁定规范是否支持针对客户端提供的版本进行验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆