0

UserA и UserB меняют объектA.filedA objectA.filedB соответственно и в одно и то же время. Поскольку они не меняют одно и то же поле, можно подумать, что совпадений нет. Это правда? или реализация pm.makePersistnace() фактически переопределяет весь объект ... Полезная информация ...GAE обновляет разные поля того же объекта

ответ

1

Это то, что вы предполагаете?

  1. Алиса извлекает объект. {a = 1, b = "Foo"}
  2. Боб извлекает объект. {a = 1, b = "Foo"}
  3. Алиса изменяет объект, изменяя b. {a = 1, b = "Bar"}
  4. Боб модифицирует объект, изменив a. {a = 2, b = "Foo"}
  5. Алиса сохраняет свою копию объекта. {a = 1, b = "Bar"}
  6. Боб сохраняет свою копию объекта. {А = 2, Ь = «Foo»}

копия Боб объекта перезаписывает копию в хранилище, потому что он упорно его всего объекта, а не только его набор измененных полей. Или, в общем, в зависимости от того, какой из них сохраняется, последний имеет весь объект, сохраненный в хранилище данных.

Вы можете исправить это, выполнив каждую операцию, выполняемую в процессе транзакции. Операции с App Engine не блокируют извлечение или изменение всего объекта локально, они просто препятствуют сохранению других пользователей. Итак:

  1. Алиса извлекает объект в транзакцию. {a = 1, b = "Foo"}
  2. Боб получает объект в транзакции. {a = 1, b = "Foo"}
  3. Алиса изменяет объект, изменяя b. {a = 1, b = "Bar"}
  4. Боб модифицирует объект, изменив a. {a = 2, b = "Foo"}
  5. Алиса пробует, чтобы сохранить объект, но не может, поскольку Боб открыл его в транзакции. Исключение будет выбрано, что Алиса поймает, прекратив ее транскрипцию и повторив ...
  6. Боб сохраняет объект без проблем, потому что Алиса закончила свою транзакцию {a = 2, b = "Foo"}
  7. Алиса повторяет свою транзакцию, возвращаясь снова. {a = 2, b = "Foo"}
  8. Алиса изменяет объект путем изменения b. {a = 2, b = "Bar"}
  9. Алиса сохраняет объект, и это работает, потому что у кого-либо еще нет транзакции. {a = 2, b = "Bar"}

Я не совсем уверен, какой пользователь получит исключение, но пока они готовы повторить попытку, когда они его видят, они оба будут в состоянии внести свои изменения в объект и в конечном итоге сохранить их.

Это называется Optimistic Locking.

+0

Вы можете пересмотреть с помощью «идентификатор» и 'name' - они оба зарезервированы в App Engine и не изменяются. –

+0

Отличная рекомендация. Переименовано в a и b. Я также переименую User A и User B в Alice и Bob, чтобы избежать еще большей путаницы. –

0

Спасибо за ваш ответ. Жаль, что реализация 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); 
    } 
} 
+0

Они также не обрабатывают 'OverQuotaException' или' CapabilityDisabledException', но это, вероятно, только потому, что это сделает пример слишком сложным, чтобы быть полезным. И правда в том, что большинство приложений никогда не будут иметь этих проблем, потому что большинство приложений не будут так сильно использоваться, что одновременные изменения являются проблемой. Некоторые приложения вообще не редактируют существующие объекты, а только создают и отображают их. Ваше приложение похоже на то, что нужно учитывать, поэтому хорошо, что вы заглянули в него. –

+1

Также, как правило, не стоит отвечать на свой вопрос обсуждением вопроса. Для этого нужны комментарии, либо по вашему вопросу, либо по ответу. –

+0

, но тогда код не выглядит красиво и трудно читается – bach

 Смежные вопросы

  • Нет связанных вопросов^_^