У меня есть описанный ниже вариант использования, который я пытаюсь выполнить sh, используя транзакции в SERIALIZABLE или REPEATALBE READ ISOLATION.
Это система книжного магазина. Самый простой, без управления пользователями и ограничения удержания цены. В книжном магазине кол-во копий вместе с ним. Для каждого запроса заказа мне нужно проверить количество доступных копий и вычесть его на 1, если оно> 0.
. Для этого я попытался использовать транзакцию, в которой я 1. прочитал объект книги и получил count 2. если count> 0 обновляет счет (count -1) в дБ.
Оба они должны быть выполнены в одной транзакции для подтверждения атомарности / согласованности.
Я написал этот метод в моем сервисе весенней загрузки:
@Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRES_NEW)
@Override
public Book updateBookQuantity(String isbn) {
Book book = null;
Optional<Book> bookRecord = bookRepository.findById(isbn);
try {
System.out.println("threadname on hold= " + Thread.currentThread().getId());
Thread.sleep(10000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("threadname resumed = " + Thread.currentThread().getId());
if (bookRecord.isPresent()) {
book = bookRecord.get();
System.out.println("book count == " + Thread.currentThread().getId() + " "+ book.getQuantity());
if (book.getQuantity() > 0) {
book = bookRecord.get();
book.setQuantity(bookRecord.get().getQuantity() - 1);
bookRepository.save(book);
} else {
throw new BookOutOfStockException(book.getTitle());
}
}
return book;
}
Теперь, где я ошибаюсь, как при попытке запустить его с помощью Rest api (нажмите 2 раза одновременно). Оба потока работают параллельно, оба считывают счетчик как 1 и обновляют его до 0. В идеале один должен был пройти, а другой должен был вызвать исключение BookOutOfStockException
. Я не настроил ничего, определяющего c для менеджера транзакций, все это обрабатывается только при весенней загрузке.
Где этот код работает неправильно? Является ли конфигурация причиной этого? Примечание: используя spring-data-jpa, база данных: mysql