У меня есть приложение для отдыха, в котором один из ресурсов может быть обновлен. Ниже приведены два метода, отвечающих за выполнение этой задачи:
-
updateWithRelatedEntities (String, Store): получает идентификатор и новый объект Store, который был создан десериализацией объекта запроса PUT, устанавливает версию (используется для оптимизации блокировки) на новый объект и вызывает обновление в транзакции.
public Store updateWithRelatedEntities(String id, Store newStore) { Store existingStore = this.get(id); newStore.setVersion(existingStore.getVersion()); em.getTransaction().begin(); newStore = super.update(id, newStore); em.getTransaction().commit(); return newStore; }
-
update (String, T): общий метод для создания обновления. Проверяет соответствие идентификаторов и выполняет операцию слияния.
public T update(String id, T newObj) { if (newObj == null) { throw new EmptyPayloadException(type.getSimpleName()); } Type superclass = getClass().getGenericSuperclass(); if (superclass instanceof Class) { superclass = ((Class) superclass).getGenericSuperclass(); } Class<T> type = (Class<T>) (((ParameterizedType) superclass).getActualTypeArguments()[0]); T obj = em.find(type, id); if (!newObj.getId().equals(obj.getId())) { throw new IdMismatchException(id, newObj.getId()); } return em.merge(newObj); }
Проблема заключается в том, что этот вызов: T obj = em.find(type, id);
запускает обновление объекта хранилища в базе данных, что означает, что мы получаем исключение OptimisticLockException при запуске merge
(поскольку версии теперь разные).
Почему это происходит? Каким будет правильный способ достичь этого?
Я вроде бы не хочу копировать свойства от newStore
до existingStore
и использовать existingStore
для merge - что, я думаю, решает проблему оптимистического блокирования.
Этот код не работает на сервере приложений, и я не использую JTA.
ИЗМЕНИТЬ:
Если я отключу существующее хранилище перед вызовом обновления, T obj = em.find(type, id);
не вызывает обновление объекта хранилища, поэтому это решает проблему. Вопрос все еще остается, но почему он вызывает его, когда объект не отсоединяется?