UserA и UserB меняют объектA.filedA objectA.filedB соответственно и в одно и то же время. Поскольку они не меняют одно и то же поле, можно подумать, что совпадений нет. Это правда? или реализация pm.makePersistnace() фактически переопределяет весь объект ... Полезная информация ...GAE обновляет разные поля того же объекта
ответ
Это то, что вы предполагаете?
- Алиса извлекает объект. {a = 1, b = "Foo"}
- Боб извлекает объект. {a = 1, b = "Foo"}
- Алиса изменяет объект, изменяя b. {a = 1, b = "Bar"}
- Боб модифицирует объект, изменив a. {a = 2, b = "Foo"}
- Алиса сохраняет свою копию объекта. {a = 1, b = "Bar"}
- Боб сохраняет свою копию объекта. {А = 2, Ь = «Foo»}
копия Боб объекта перезаписывает копию в хранилище, потому что он упорно его всего объекта, а не только его набор измененных полей. Или, в общем, в зависимости от того, какой из них сохраняется, последний имеет весь объект, сохраненный в хранилище данных.
Вы можете исправить это, выполнив каждую операцию, выполняемую в процессе транзакции. Операции с App Engine не блокируют извлечение или изменение всего объекта локально, они просто препятствуют сохранению других пользователей. Итак:
- Алиса извлекает объект в транзакцию. {a = 1, b = "Foo"}
- Боб получает объект в транзакции. {a = 1, b = "Foo"}
- Алиса изменяет объект, изменяя b. {a = 1, b = "Bar"}
- Боб модифицирует объект, изменив a. {a = 2, b = "Foo"}
- Алиса пробует, чтобы сохранить объект, но не может, поскольку Боб открыл его в транзакции. Исключение будет выбрано, что Алиса поймает, прекратив ее транскрипцию и повторив ...
- Боб сохраняет объект без проблем, потому что Алиса закончила свою транзакцию {a = 2, b = "Foo"}
- Алиса повторяет свою транзакцию, возвращаясь снова. {a = 2, b = "Foo"}
- Алиса изменяет объект путем изменения b. {a = 2, b = "Bar"}
- Алиса сохраняет объект, и это работает, потому что у кого-либо еще нет транзакции. {a = 2, b = "Bar"}
Я не совсем уверен, какой пользователь получит исключение, но пока они готовы повторить попытку, когда они его видят, они оба будут в состоянии внести свои изменения в объект и в конечном итоге сохранить их.
Это называется Optimistic Locking.
Спасибо за ваш ответ. Жаль, что реализация makePersistence() должна записывать объект WHOLE в хранилище данных, а не только к полям, которые были изменены. Этот факт фактически заставляет ЛЮБЫЕ обновления общего объекта в GAE использовать транзакцию, как правило. Далее - в таких случаях вы должны реализовать «механизм повтора», поскольку может произойти исключение в транзакции.
Итак ... обновление любой общий объект в GAE всегда должны иметь следующие дополнительные услуги:
- сделать это в рамках транзакции
- реализовать механизм Retry
Большинство примеров Google, в их сайт на самом деле не учитывает это. Как будто они предполагая, что большинство приложений не будут использоваться общие объекты
Например (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();
}
}
ИЛИ:
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);
}
}
Они также не обрабатывают 'OverQuotaException' или' CapabilityDisabledException', но это, вероятно, только потому, что это сделает пример слишком сложным, чтобы быть полезным. И правда в том, что большинство приложений никогда не будут иметь этих проблем, потому что большинство приложений не будут так сильно использоваться, что одновременные изменения являются проблемой. Некоторые приложения вообще не редактируют существующие объекты, а только создают и отображают их. Ваше приложение похоже на то, что нужно учитывать, поэтому хорошо, что вы заглянули в него. –
Также, как правило, не стоит отвечать на свой вопрос обсуждением вопроса. Для этого нужны комментарии, либо по вашему вопросу, либо по ответу. –
, но тогда код не выглядит красиво и трудно читается – bach
Вы можете пересмотреть с помощью «идентификатор» и 'name' - они оба зарезервированы в App Engine и не изменяются. –
Отличная рекомендация. Переименовано в a и b. Я также переименую User A и User B в Alice и Bob, чтобы избежать еще большей путаницы. –