Как определить, существует ли объект для данного ключа в хранилище данных Google AppEngine с помощью Java?

Я пытаюсь перенести пример Sharding Counters (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) поддерживаются только операции получения и размещения. Итак, как я могу заблокировать объект с помощью еще не существующего ключа (т. е. без «получения») и убедиться, что я первый и единственный, кто его создает?


person Community    schedule 23.05.2009    source источник
comment
Разве вы не можете просто поймать JDOObjectNotFoundException и создать объект в этом случае?   -  person Nick Johnson    schedule 25.05.2009
comment
Я мог бы это сделать, но это все еще не транзакция. В тот момент, когда я создаю новый шард со счетом 1, может прийти еще один запрос. Я посмотрю на группы сущностей и родительские ключи. Может быть, это путь.   -  person    schedule 25.05.2009
comment
Это транзакционный, если вы делаете это в рамках одной транзакции. Транзакция (как и ожидалось) не будет зафиксирована, если объект, который вы пытались получить, был вставлен или обновлен до того, как вы смогли зафиксировать. Именно так работает get_or_insert Python SDK.   -  person Nick Johnson    schedule 26.05.2009


Ответы (1)


проверьте демо-код здесь

http://code.google.com/p/googleappengine/source/browse/trunk/java/demos/shardedcounter/README

person Chii    schedule 24.05.2009
comment
Спасибо за указание на пример. Я присмотрелся, но пришел к выводу, что пример с Java тоже не транзакционный, т.е. есть шанс, что шард будет инкрементирован до того, как будет создан. Взгляните на ShardedCounter.increment(int). Он запрашивает осколок с заданным индексом, и только если он может его найти, он увеличивает его. Если он не может найти его, он просто удаляет его. Кроме того, похоже, что он не использует никаких транзакций или механизмов блокировки. Что делать, если шард обновляется одновременно? Я должен что-то упустить... - person ; 25.05.2009