如何使用Java确定Google AppEngine数据存储中给定密钥的对象是否存在?

如何使用Java确定Google AppEngine数据存储中给定密钥的对象是否存在?,java,google-app-engine,sharding,google-cloud-datastore,Java,Google App Engine,Sharding,Google Cloud Datastore,我正在尝试将切分计数器示例(code.google.com/appengine/articles/Sharding_Counters.html)移植到Java。唯一的问题是JavaAPI没有类似于Python的“get_by_key_name”的调用。这是基本思想: Transaction tx = pm.currentTransaction(); Key key = KeyFactory.createKey(CounterShard.class.

我正在尝试将切分计数器示例(code.google.com/appengine/articles/Sharding_Counters.html)移植到Java。唯一的问题是JavaAPI没有类似于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。我可以运行查询来确定给定名称的计数器是否存在,但这不是事务性的。另一个线程也可以这样做,最终两者都将创建一个具有相同键的对象


据我所知,事务(对于JavaAPI)中支持的唯一操作是get和put。那么,我如何通过密钥锁定一个还不存在的对象(即,没有“get”),并确保我是第一个也是唯一一个创建它的人?

检查这里的演示代码


感谢您指出这个例子。我仔细研究了一下,但得出的结论是,Java示例也不是事务性的,也就是说,碎片在创建之前有可能会递增。看看ShardedCounter.increment(int)。它查询具有给定索引的碎片,并且仅当它能够找到该碎片时才递增该碎片。如果它找不到它,就把它扔了。它似乎也没有使用任何事务或锁定机制。如果一个碎片同时更新怎么办?我肯定遗漏了什么…你不能捕获JDOObjectNotFoundException并在这种情况下创建实体吗?我可以这样做,但这仍然不是事务性的。当我创建一个计数为“1”的新碎片时,另一个请求可能会出现。我将研究实体组和父键。也许这是一种方式。如果你在一个事务中完成它,那么它就是事务性的。如果在您提交之前插入或更新了您尝试获取的实体,则事务将(如预期)无法提交。这正是pythonsdk的get_或_insert的操作方式。