GAE обновляет разные поля одной и той же сущности - PullRequest
0 голосов
/ 07 апреля 2010

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

Ответы [ 2 ]

1 голос
/ 07 апреля 2010

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

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

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

Это можно исправить, выполнив каждую из их операций get-set-and-persist в транзакции. Транзакции App Engine не блокируют весь объект от извлечения или изменения локально, они просто предотвращают сохранение других пользователей. Итак:

  1. Алиса получает объект в транзакции. {a = 1, b = "Foo"}
  2. Боб получает объект в транзакции. {a = 1, b = "Foo"}
  3. Алиса изменяет объект, изменяя b. {a = 1, b = "Bar"}
  4. Боб изменяет объект, изменяя. {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"}

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

Это называется Оптимистическая блокировка .

0 голосов
/ 07 апреля 2010

Спасибо за ваш ответ. Жаль, что реализация makePersistence () предназначена для записи целого объекта в хранилище данных, а не только в поля, которые были изменены. Этот факт фактически заставляет ЛЮБОЕ обновление общего объекта в GAE использовать транзакцию как правило. Более того - в таких случаях вы должны реализовать «механизм повторных попыток», поскольку в транзакции может возникнуть исключение.

Итак ... обновление любого общего объекта в GAE должно ВСЕГДА иметь эти дополнения:

  • сделать это в рамках транзакции
  • реализовать механизм повтора

Большинство примеров 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();
    }
}

OR

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);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...