Я хочу продать фиксированное количество товара клиенту.Как управлять параллелизмом весной jpa? - PullRequest
0 голосов
/ 12 декабря 2018

Spring Boot с пружинными данными jpa.

У меня есть сценарий использования, когда я хочу продать n продуктов и получил запрос на продукт n + 1 за один раз.Итак, как я могу гарантировать, что я должен продавать только n продуктов и не выполнить все другие запросы.

Предположим, у меня есть 10 количество для любого идентификатора продукта 1. И получил 11 запросов одновременно для этого конкретноготовар.Как я могу гарантировать, что система продаст только 10 товаров и не выполнит последний запрос из-за отсутствия на складе.

Все запросы могут быть выполнены одновременно.

Я использую MySql.

Если я использую @version, он завершает все остальные транзакции, кроме 1-й.

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Version;

@Entity
public class ProductStockTable {

    @javax.persistence.Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long Id;

    private Long productId;

    @Version
    private Long version;

    private Long currentStock;

    public Long getId() {
        return Id;
    }

    public void setId(Long id) {
        Id = id;
    }

    public Long getProductId() {
        return productId;
    }

    public void setProductId(Long productId) {
        this.productId = productId;
    }

    public Long getVersion() {
        return version;
    }

    public void setVersion(Long version) {
        this.version = version;
    }

    public Long getCurrentStock() {
        return currentStock;
    }

    public void setCurrentStock(Long currentStock) {
        this.currentStock = currentStock;
    }
}

    @Transactional
public boolean checkStock(Long productId, Integer stock) {

        ProductStockTable ps = stockRepo.findById(productId);
        if (ps.getCurrentStock() > stock) {
            ps.setCurrentStock(ps.getCurrentStock()-stock);
            stockRepo.save(ps);
            return true;
        }
        return false;

    }

Если я сделаю ограничение MySql not negative для currentStock, оно также не будет работать.

Есть ли какой-нибудь возможный способ добиться этого при загрузке Spring?

Ответы [ 2 ]

0 голосов
/ 12 декабря 2018

Вы должны прочитать о LockMode.

. Одним из решений будет использование PESSIMISTIC_WRITE при чтении строки из вашей сущности ProductStockTable.Этот режим предотвратит все остальные операции чтения, в основном думайте об этом как об эксклюзивной блокировке в этой строке, пока вы не закончите с этим.Затем, как только блокировка снята, следующий соперник может заблокировать ее и т. Д.

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

0 голосов
/ 12 декабря 2018

Позвоните в вашу функцию проверки прямо перед завершением процесса?Один раз в начале, один раз в конце и сразу после обновления базы данных и изменения запаса.

Другой вариант может быть, когда вам отправляют запрос - обновите этот запас до завершения (так чтозаблокирован пока его в чьей-то тележке).Поместите таймер в корзину, чтобы через 5 минут он автоматически пополнялся (я предпочитаю вариант 1, обновление базы данных обычно устанавливает временную блокировку, которая останавливает оператор select до тех пор, пока обновление не будет завершено)

...