繁体   English   中英

使用乐观锁定创建新的数据存储区实体(Google App Engine Java / JPA)

[英]Creating new Datastore entities with optimistic locking (Google App Engine Java / JPA)

我有一个JPA实体类User,用户名为@ID,没有父实体组。 我需要确保当两个并行事务尝试使用相同的用户名持久保存用户时,只提交一个用户并回滚另一个用户。

例:

User bob = new User("bob");
EntityTransaction transaction = em.getTransaction();

try {
  transaction.begin();
  User u = em.find(User.class, bob.id());
  if (u == null) {
    em.persist(bob);
  } else {
    // identical user already existed before the transaction
    throw new UserExistsException(); 
  }
  transaction.commit();
} catch (RollbackException e) {
    // identical user was created during the transaction
    throw new UserExistsException();
}

根据数据存储区文档,交易遵循乐观的锁定方法:

“当事务开始时,App Engine通过检查事务中使用的实体组的上次更新时间来使用乐观并发控制。在为实体组提交事务时,App Engine会再次检查上次使用的实体组的更新时间。如果它自我们的初始检查后发生了变化,App Engine会抛出异常。“ https://developers.google.com/appengine/docs/java/datastore/transactions

在持久化事务之前不存在的新(根)实体时,这是否有效? 在我的情况下,App Engine会检查另一个事务是否同时持有具有相同ID的用户? 如果是这样,我是否需要一个明确的@Version字段用于此目的?

对此问题进行了一些长期的搁置:答案为“是”,上述代码应按预期工作。 简而言之,乐观并发控制机制将使用(根)实体的类型“用户”和给定标识符“bob”来比较两个事务中使用的(新)实体组。 数据存储区文档现在还明确地解决了创建案例:

当两个或多个事务尝试同时更改同一实体组时(更新现有实体或创建新实体),第一个提交事务将成功,所有其他事务将在提交时失败。

使用JPA,在这种情况下你会得到一个RollbackException。 低级API将引发ConcurrentModificationException。 如果您正在使用Objectify(我强烈建议),将自动重试失败的事务。 因此,您应该确保在事务中首先检查实体是否存在,除非您想在第二次尝试时覆盖它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM