Исключение OptimisticLockException при использовании объединения JPA()
У меня есть приложение для отдыха, в котором один из ресурсов может быть обновлен. Ниже приведены два метода, отвечающих за выполнение этой задачи:
-
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);
не вызывает обновление объекта хранилища, поэтому это решает проблему. Вопрос все еще остается, но почему он вызывает его, когда объект не отсоединяется?
Ответы
Ответ 1
Я не вижу вашу сущность из кода, который вы добавили, но я считаю, что вам не хватает ключевого слова с оптимистичной блокировкой → @Version
аннотации в поле версии.
Если у вас есть это поле на вашей сущности, то контейнер должен иметь возможность выполнять процедуру слияния без проблем. Пожалуйста, взгляните на
Оптимистическая блокировка также хорошая статья не нарушать оптимистичную блокировку