Arhn - архитектура программирования

Различные методы REST изменяют один и тот же объект — RollbackException, OptimisticLockException, StaleStateException

Я использую Java 8, Hibernate 5.1.0.Final, Guice 4.1.0, Jersey 1.19. У меня есть несколько методов REST, которые могут изменять один и тот же объект — сущность, загруженную из базы данных. Когда они запускаются одновременно и изменяют один и тот же элемент, я получаю:

javax.persistence.RollbackException: Error while committing the transaction
    at org.hibernate.jpa.internal.TransactionImpl.commit(TransactionImpl.java:86)

Caused by: javax.persistence.OptimisticLockException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1

Caused by: org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1

Возможные решения:

Есть ли другие варианты? Каков наилучший способ справиться с этой проблемой?

ОБНОВЛЕНИЕ 1

Я попытался реализовать повторную попытку:

public void changeItemName(Long id, String name){

    Item item = itemDAO.find(id);
    item.setName(name);

    try {
        itemDAO.save(item);
    } catch (RollbackException | OptimisticLockException | StaleStateException e) {
        logger.warn("Retry method after " + e.getClass().getName()); 
        changeItemName(id, name);
    }
}

Но я получаю:

javax.persistence.RollbackException: Error while committing the transaction
at org.hibernate.jpa.internal.TransactionImpl.commit(TransactionImpl.java:86)

Caused by: javax.persistence.PersistenceException: org.hibernate.exception.GenericJDBCException: could not update: [com.example.Item#1]
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1692)

Caused by: org.hibernate.exception.GenericJDBCException: could not update: [com.example.Item#1]
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:47)

Caused by: org.postgresql.util.PSQLException: This statement has been closed.
at org.postgresql.jdbc2.AbstractJdbc2Statement.checkClosed(AbstractJdbc2Statement.java:2653)

Ответы:


1
  1. Синхронизация по объекту в методах REST Я бы сказал, что это невозможно. Представьте, что один и тот же сервис работает на 2 узлах.

  2. Постоянно обновлять состояние объекта снова нельзя. Обновление может произойти только между двумя обновлениями.

  3. Этот в порядке. Принцип КАС. Пока версия неверна, попытайтесь сохранить изменения. Но на самом деле это зависит от вашей бизнес-логики. Например. Существует объект User, начальное имя которого было «name1». Первый вызов изменяет его с "name1" на "name2". Второй вызов пытается измениться с "name1" на "name3". Мы можем либо (A) изменить имя, подавляя обновление «name1» -> «name2», либо (B) отклонить сообщение об изменении вызывающей стороне, чтобы обновить, чтобы увидеть фактическое состояние и применить изменения к фактическому состоянию.

Если мы пытаемся изменить, например. подход баланса счета (A) недействителен и нам нужен (B).

Вы должны решить, что делать в соответствии с бизнес-логикой, которая вам там нужна.

ОБНОВЛЕНИЕ: так не пойдет. Вам нужно поймать это выше - где запускается транзакция и сделать это отдельной транзакцией.

Предположим, у вас есть

@Service
public class MyServiceImpl
    @Transactional
    public void changeItemName(Long id, String name) {
    }

где может произойти исключение оптимистической блокировки. Если вы вызываете метод только из блока catch, новая транзакция не запускается, потому что вызывается метод не прокси.

Вместо этого вы можете сделать что-то вроде этого

@Service
public class MyServiceImpl
    @Autowired
    private MyService myService;
    @Transactional
    public void changeItemName(Long id, String name) {
      catch() {
        myService.changeItemName(id, name);
      }
    }
03.05.2017
  • Попытался повторить попытку с библиотекой vladmihalcea.com/2013/11 /15/optimistic-locking-retry-with-jpa, но это не сработало. Теперь добавили try-catch для исключения, а затем повторите метод, но я столкнулся с другой проблемой - при повторной попытке объект извлекается из кеша, версия не обновляется, и я получаю бесконечный цикл. 03.05.2017
  • Пробовал обновить, объединить, выселить, очистить перед повторной попыткой, но не помогло. 03.05.2017
  • Я думаю, вы должны поймать исключение, затем выселить (я полагаю, это должно сработать) старый объект, снова получить объект (entityManager.refresh(entity)), применить изменения и сохранить его. Убедитесь, что вы не копируете версию каким-либо образом. 03.05.2017
  • После перезагрузки/обновления я получаю обновленный объект, но его невозможно сохранить из-за другого исключения JPA/Hibernate. 03.05.2017
  • Реализовано, как было предложено, но все равно получается то же исключение. Использование @com.google.inject.persist.Transactional 04.05.2017
  • Создан отдельный вопрос с точной конфигурацией: stackoverflow.com/questions/43780675/ 05.05.2017
  • Новые материалы

    Коллекции публикаций по глубокому обучению
    Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

    Представляем: Pepita
    Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

    Советы по коду Laravel #2
    1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

    Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
    Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

    3 способа решить квадратное уравнение (3-й мой любимый) -
    1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

    Создание VR-миров с A-Frame
    Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

    Демистификация рекурсии
    КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..