@Version注释

@Version注释如何在JPA中工作?

我找到了各种答案,其摘录如下:

JPA在您的实体中使用版本字段来检测对同一数据存储区记录的并发修改。 当JPA运行时检测到试图同时修改同一记录时,它会向尝试提交最后的事务抛出异常。

但我仍然不确定它是如何工作的。


同样来自以下几行:

您应该考虑版本字段不可变。 更改字段值有未定义的结果。

这是否意味着我们应该将我们的版本字段声明为final


但我仍然不确定它是如何工作的?

假设实体MyEntity具有注释version属性:

@Entity
public class MyEntity implements Serializable {    

    @Id
    @GeneratedValue
    private Long id;

    private String name;

    @Version
    private Long version;

    //...
}

在更新时,用@Version注释的字段将被增加并添加到WHERE子句中,如下所示:

UPDATE MYENTITY SET ..., VERSION = VERSION + 1 WHERE ((ID = ?) AND (VERSION = ?))

如果WHERE子句无法匹配记录(因为同一个实体已被另一个线程更新),那么持久性提供者将抛出一个OptimisticLockException

这是否意味着我们应该将我们的版本字段声明为final

不,但你可以考虑让制定者保护起来,因为你不应该叫它。


尽管@Pascal答案是完全有效的,但从我的经验来看,我发现下面的代码有助于实现乐观锁定:

@Entity
public class MyEntity implements Serializable {    
    // ...

    @Version
    @Column(name = "optlock", columnDefinition = "integer DEFAULT 0", nullable = false)
    private long version = 0L;

    // ...
}

为什么? 因为:

  • 如果使用@Version注释的@Version被意外设置为null乐观锁定将不起作用
  • 由于这个专业领域不一定是对象的商业版本,为了避免误导,我更愿意将这个领域命名为optlock而不是version
  • 如果应用程序使用JPA将数据插入数据库,则第一点并不重要,因为JPA供应商将在创建时为@version字段强制执行0 。 但几乎总是普通的SQL语句也在使用中(至少在单元/集成测试期间)。


    每次在数据库中更新实体时,版本字段都会增加1。 更新数据库中的实体的每个操作都将在其查询中附加WHERE version = VERSION_THAT_WAS_LOADED_FROM_DATABASE

    在检查受影响的操作行时,jpa框架可以确保在加载和持久化实体之间没有并发修改,因为在加载和保持之间版本号已经增加时,查询在数据库中找不到实体。

    链接地址: http://www.djcxy.com/p/89587.html

    上一篇: @Version annotation

    下一篇: Why is memmove faster than memcpy?