Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/379.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 我可以使用@Version字段自动检查并发修改吗?_Java_Hibernate_Jpa_Locking - Fatal编程技术网

Java 我可以使用@Version字段自动检查并发修改吗?

Java 我可以使用@Version字段自动检查并发修改吗?,java,hibernate,jpa,locking,Java,Hibernate,Jpa,Locking,我有一个带有注释的@Version字段的实体。在前端显示数据时,我试图使用此字段检查对实体的并发修改。然而,这似乎没有产生预期的效果 @Entity public class User { @Id @GeneratedValue(strategy=GenerationType.TABLE, generator="UUIDGenerator") @Column(name="id") private Long id; @NotNull private String use

我有一个带有注释的
@Version
字段的实体。在前端显示数据时,我试图使用此字段检查对实体的并发修改。然而,这似乎没有产生预期的效果

@Entity
public class User
{

  @Id
  @GeneratedValue(strategy=GenerationType.TABLE, generator="UUIDGenerator")
  @Column(name="id")
  private Long id;

  @NotNull
  private String username;
  private String password;

  @Version
  @Column(name="version")
  private Integer version;
}
我要求前端在发布数据时将
version
字段发送回服务器。在服务器端,我使用PK从数据库检索实体,用发布的值更新版本(以及其他字段),然后让entitymanager持久化实体。我希望,如果同时版本发生更改,它会自动抛出StaleObject异常,但它什么也不做

进一步阅读后,似乎不允许我以编程方式修改版本字段。
根据JPA规范,应用程序不允许修改版本字段:

JPA 2.0最终规范,第3.4.2节:

实体可以访问其版本字段或属性的状态,或者 导出方法以供应用程序用于访问版本,但 不能修改版本值。除第节所述的例外情况外 4.10中,仅允许持久性提供程序设置或更新对象中版本属性的值


在这一点上,我唯一的选择是每次手动检查发布数据的版本与DB的版本吗?难道没有办法让JPA提供商为我这样做吗?

为什么不使用JPA EntityManager的合并方法

此方法将首先将实体提取到持久化上下文,并将所有值从实体(分离)复制到持久化实体。当事务刷新时,JPA将为您检查版本。如果它过时,将抛出乐观锁异常。使用此方法,实际上不需要自己检查版本

乐观锁定是一种用于确保更新 与实体状态相对应的数据库数据 仅当自 实体状态被读取

如果该规则被破坏,则抛出的异常是OptimisticLockException

其中一些是考虑因素

  • 您的提供程序应该支持乐观锁定
  • 您可以调用一些方法来启用这种锁定

    锁(java.lang.Object实体,LockModeType lockMode)

    查找(java.lang.Class entityClass,java.lang.Object primaryKey,LockModeType lockMode)

    刷新(java.lang.Object实体,LockModeType lockMode)


  • 我考虑过使用它,但这意味着整个实体正在合并。为了做到这一点,因为我想从客户端复制选择性字段,我必须首先从数据库中检索实体,分离它,然后合并它。这种做法违背了JPA坚持的“魔力”,即不需要每次都指导它坚持下去。虽然我并没有告诉它要持久化,但在这个上下文中,合并几乎是一样的。如果您只想持久化某些属性,那么可以将持久化实体提取到持久化上下文中,并手动将这些属性复制到其中。我认为JPA会在交易结束时为您处理剩下的事情(比如版本)。版本只是维护优化锁的机制之一(我听说其他一些持久性框架可能使用时间戳而不是版本),因此最好让持久性框架为您管理优化锁,但不要直接接触它;但是,当您检索数据并将其发送给客户机时,客户机在将数据发送回您之前需要花费一些时间,您需要确保数据库上的数据自那时起没有更改。因此,即使我可以从数据库中检索行并直接更新它(通过将字段复制到该实体中),我也必须首先确保正在更新的行的版本与客户端返回的版本相同(即:在此期间没有人修改该行)。因此需要使用
    @Version
    字段。