【问题标题】:How to I determine if an object exists for a given key in the Google AppEngine datastore using Java?如何使用 Java 确定 Google AppEngine 数据存储中的给定键是否存在对象?
【发布时间】:2009-05-23 20:15:10
【问题描述】:

我正在尝试将分片计数器示例 (code.google.com/appengine/articles/sharding_counters.html) 移植到 Java。唯一的问题是 Java API 没有类似于 Python 的“get_by_key_name”的调用。这是基本思想:

            Transaction tx = pm.currentTransaction();
            Key key = KeyFactory.createKey(CounterShard.class.getSimpleName(), counter + randomIndex);
            CounterShard shard = pm.getObjectById(CounterShard.class, key);
            if (shard == null) {  // API does not work this way...
                shard = new CounterShard(key, counter);
            }
            shard.increment();
            pm.makePersistent(shard);
            tx.commit();

不幸的是,这在我第一次运行时会引发 JDOObjectNotFoundException。我可以运行查询以确定给定名称的计数器是否存在,但这不是事务性的。另一个线程可以做同样的事情,最后两者都会创建一个具有相同键的对象。

据我了解,事务中支持的唯一操作(对于 Java API)是 get 和 put。那么如何通过键锁定一个尚不存在的对象(即没有“get”)并确保我是第一个也是唯一一个创建它的对象?

【问题讨论】:

  • 在这种情况下你不能捕获 JDOObjectNotFoundException 并创建实体吗?
  • 我可以这样做,但这仍然不是事务性的。在我创建一个计数为“1”的新分片时,可能会出现另一个请求。我将研究实体组和父键。也许这就是要走的路。
  • 如果您在单个事务中执行此操作,则它是事务性的。如果您尝试获取的实体在您提交之前被插入或更新,则事务将(如预期的那样)无法提交。这正是 Python SDK 的 get_or_insert 的操作方式。

标签: java google-app-engine sharding google-cloud-datastore


【解决方案1】:

【讨论】:

  • 感谢您指出示例。我仔细看了看,但得出的结论是 Java 示例也不是事务性的,即分片有可能在创建之前递增。看看 ShardedCounter.increment(int)。它查询具有给定索引的分片,并且只有当它可以找到它时才会增加它。如果它找不到它,它就会丢弃它。它似乎也没有使用任何事务或锁定机制。如果一个分片同时更新怎么办?我一定是错过了什么......
猜你喜欢
  • 2017-04-05
  • 2014-08-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-12
  • 1970-01-01
  • 1970-01-01
  • 2012-02-14
相关资源
最近更新 更多