Исключение 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 аннотации в поле версии. Если у вас есть это поле на вашей сущности, то контейнер должен иметь возможность выполнять процедуру слияния без проблем. Пожалуйста, взгляните на Оптимистическая блокировка также хорошая статья не нарушать оптимистичную блокировку