0

UserA和用户B分别和同时改变objectA.filedA objectA.filedB的。 因为他们没有改变同一个领域,人们可能会认为没有重叠。 这是真的吗? 或执行pm.makePersistnace()实际覆盖整个对象... 相关提示...GAE更新不同的领域相同的实体

回答

1

这是你正在设想的事情吗?

  1. 爱丽丝获取对象。 {a = 1,b =“Foo”}
  2. Bob检索对象。 {a = 1,b =“Foo”}
  3. Alice通过改变b来修改对象。 {a = 1,b =“Bar”}
  4. Bob通过更改a来修改对象。 {a = 2,b =“Foo”}
  5. Alice坚持她的对象副本。 {a = 1,b =“Bar”}
  6. Bob坚持他的对象副本。 {A = 2,B =“富”}

鲍勃的对象的副本将覆盖数据存储中的副本,因为他坚持他的整个对象,不只是他的一套改变字段。或者,一般来说,无论哪一个持续存在,都会在数据存储中保留整个对象的

您可以通过在一个事务中运行他们的每一个GET-设置和持续运营的解决这个问题。 App Engine事务不会锁定整个对象在本地检索或修改,它们只会阻止其他用户持续存在。所以:

  1. Alice在事务中检索对象。 {a = 1,b =“Foo”}
  2. Bob在事务中检索对象。 {a = 1,b =“Foo”}
  3. Alice通过改变b来修改对象。 {a = 1,b =“Bar”}
  4. Bob通过更改a来修改对象。 {A = 2,B = “foo” 的}
  5. 爱丽丝尝试来持久对象,但不能,因为Bob有它在一个事务中打开。 Alice将通过结束她的交易并重试来捕获...
  6. 由于Alice完成了他的交易{a = 2,b =“Foo”},所以Bob坚持这个对象,没有问题
  7. Alice重新检索她的交易。 {a = 2,b =“Foo”}
  8. Alice通过改变b来修改对象。 {A = 2,B =“酒吧”}
  9. 爱丽丝仍然存在的对象,它的作品,因为没有其他人有开放的交易。 {A = 2,B =“酒吧”}

我没有绝对的把握哪些用户将得到异常,但只要他们愿意重试当他们看到它,他们就要最终能够对对象进行修改并坚持下去。

这就是所谓的Optimistic Locking

+0

您可能需要使用“身份证”重新考虑和'name' - 它们都是App Engine中的保留字,并且不可修改。 – 2010-04-07 16:38:24

+0

非常好的建议。重命名为a和b。我还会将用户A和用户B重命名为Alice和Bob,以避免更多混淆。 – 2010-04-07 16:48:52

0

感谢您的回答。 可惜makePersistence()实现是将WHOLE对象写入数据存储区,而不是写入已更改的字段。 这个事实实际上是强制GAE中的任何共享对象更新作为规则使用事务。 此外 - 在这种情况下,您必须实施“重试机制”作为可能发生的事务中的异常。

所以...更新在GAE任何共享的对象应该始终有这些额外:

  • 做交易
  • 内实现重试机制

大多数谷歌在自己的例子网站实际上没有考虑到这一点。仿佛他们假设大多数应用程序将无法使用共享对象

例如(http://code.google.com/appengine/docs/java/datastore/creatinggettinganddeletingdata.html):

public void updateEmployeeTitle(User user, String newTitle) { 
    PersistenceManager pm = PMF.get().getPersistenceManager(); 
    try { 
     Employee e = pm.getObjectById(Employee.class, user.getEmail()); 
     if (titleChangeIsAuthorized(e, newTitle) { 
      e.setTitle(newTitle); 
     } else { 
      throw new UnauthorizedTitleChangeException(e, newTitle); 
     } 
    } finally { 
     pm.close(); 
    } 
} 

OR:

public void updateEmployeeTitle(Employee e, String newTitle) { 
    if (titleChangeIsAuthorized(e, newTitle) { 
     e.setTitle(newTitle); 
     PersistenceManager pm = PMF.get().getPersistenceManager(); 
     try { 
      pm.makePersistent(e); 
     } finally { 
      pm.close(); 
     } 
    } else { 
     throw new UnauthorizedTitleChangeException(e, newTitle); 
    } 
} 
+0

他们也没有处理'OverQuotaException's或'CapabilityDisabledException's,但这可能只是因为它会使这个例子太复杂而无用。事实是,大多数应用程序永远不会遇到这些问题,因为大多数应用程序不会那么频繁地使用,以至于同时编辑是一个问题。有些应用根本不编辑现有实体,只创建并显示它们。你的应用程序似乎需要考虑它,所以你已经研究过它是一件好事。 – 2010-04-07 16:55:06

+1

此外,通过讨论有关问题回答自己的问题通常不是一个好主意。这就是你的问题或答案的意见。 – 2010-04-07 16:57:24

+0

但随后代码不会很好地显示并难以阅读 – bach 2010-04-07 17:46:02