Spring data JPA - одновременный доступ к Entity - PullRequest
0 голосов
/ 28 апреля 2018

Я хочу убедиться, что только 1 поток имеет доступ к сущности в моей сервисной функции. Как это сделать?

Пример: я хочу безопасно уменьшить количество: даже если несколько потоков выполняют OrderService.remove (Product), я не хочу 2 обновления БД с одинаковым значением счетчика.

В многопоточной среде environemnt 2 потоки могут выполнять эту функцию одновременно, они могут считывать одно и то же значение счетчика и, следовательно, обновлять БД с тем же уменьшенным значением. Это нежелательно.

Продукт:

@Entity
public class Product {

    @Id
    @GeneratedValue
    private UUID id;

    private Integer count;

    ...

ProductService:

@Service
@Transactional
public class ProductService {

    public void remove(UUID productId) {

        final Product product = productRepository.findById(productId);

        // TODO how to lock product, so no other thread can modify it before this operation is committed?
        final Integer currentCount = product.getCount();
        product.setCount(currentCount-1);

    }

}

1 Ответ

0 голосов
/ 28 апреля 2018

Вы хотите, чтобы remove(..) метод работал как транзакция (чтобы при этом методе не происходило одновременное обновление Базы данных *1004*). Для этого необходимо пометить метод как @Transactional.
Пока сериализуемость гарантирует, что эффект параллельных транзакций эквивалентен их последовательному (то есть последовательному) выполнению, достаточно явно указать уровень изоляции Isolation.SERIALIZABLE.

@Transactional(isolation = Isolation.SERIALIZABLE)
public void remove(UUID productId) {
    ...
}

Если вам нужна более продвинутая логика в работе с транзакциями, вы можете использовать более низкие уровни изоляции и политику повторных попыток: @Retryable(StaleStateException.class).
Подробнее см. https://github.com/spring-projects/spring-retry.

...