2015-03-03 4 views
0

Здесь the sample project, где воспроизводится исключение.OptimisticLockException с одновременным обновлением JPA под Spring Boot

Этот образец иллюстрирует проблему, когда многие параллельные транзакции изменяют баланс счета. У учетной записи может быть связано несколько объектов Карт. Сделки связаны с порядком и последними по времени. Каждый поток выполняет следующим образом:

  1. запросы клиента/заказ/{Хашид} 'для первого доступного Поручения данной карты хэш-идентификатор
  2. клиент начинает новый ТХ для данного заказа - «/ TX/{OrderId}/start '
  3. клиент завершает tx -'/tx/{txId}/stop/{amount} ', где сумма tx вычитается из баланса Счета.

Entity блокираторы

счет и заказать сущности версионируются с @ javax.persistence.Version. В последнем шаге объект Счет заблокирован с пессимистической блокировки записи:

@Override 
public Account getLockedAccount(Integer id) { 
    final Account account = findOne(id); 
    em.lock(account, LockModeType.PESSIMISTIC_WRITE); 
    return account; 
} 

Тестирование

Чтобы проверить использование параллельного доступа JMeter сценарий SRC/главная/ресурсы/StressTest.jmx. NB: Extra libs должны быть установлены в JMeter для запуска сценария из-за использования JSON Path extractor. С помощью этих специальных настроек на среднем ноутбуке вы можете получить около 10% ошибок для запроса TxEnd:

{ 
"timestamp":1425407408204, 
"status":500, 
"error":"Internal Server Error", 
"exception":"org.springframework.orm.ObjectOptimisticLockingFailureException", 
"message":"Object of class [sample.data.jpa.domain.Account] with identifier [1]: optimistic locking failed; nested exception is org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [sample.data.jpa.domain.Account#1]", 
"path":"/tx/1443/stop/46.4" 
} 

Вопроса

Несмотря на пессимистическую используя блокировку записи я все еще получаю оптимистическое исключение блокировки. Есть ли другой подход к обеспечению целостности учетной записи без создания очереди выполнения задачи для всех обновлений или методов синхронизации?

UPD: Обходной с задачей исполнителя помещается в another branch. Весна ThreadPoolTaskExecutor в сочетании с транзакционной задачей устраняет проблему.

ответ

0

Между поиском и блокировкой объект Account, возможно, уже был изменен. Вы должны сделать это в одном операторе

EM.find (Account.class, идентификатор, LockModeType.PESSIMISTIC_WRITE)

+0

Перед использованием EntityManager я попытался @Lock аннотацию: '@Lock (LockModeType.PESSIMISTIC_WRITE) Счет findOne (Integer integer); '. Полную реализацию предыдущей версии можно найти здесь (https://github.com/EvgeniGordeev/spring-jpa-optimistic-lock/blob/dedc33d5f5462819e1b5fb7ce165d14e27480b96/src/main/java/sample/data/jpa/service/AccountRepository. Ява). Внутри Spring SimpleJpaRepository используется тот же эквивалент 'em.find (domainType, id, type, hints)', где hints является текущим LockModeType. –

+0

Так что это не помогает. –

Смежные вопросы