Spring data выдает ошибку при работе с одним объектом в многопоточной среде: пакетное обновление вернуло неожиданную строку - PullRequest
0 голосов
/ 22 февраля 2020

У меня есть проблема, которую я не могу решить и, возможно, не совсем понимаю. Я буду благодарен за любую помощь.

У меня есть код:

    @Override
    @Transactional
     public void addRecentGoods(Profile profile, Long cmId) {
        int viewMaxProducts = settingsService.getMaxNumberlistOfViewProducts();

        List<RecentGoods> recentGoods = profile.getRecentGoods();

        for (RecentGoods recentGood : recentGoods) {
            if (recentGood.getCmId().equals(cmId)) {
                recentGood.setDateTime(DateUtil.getDate());
                sortedAndLimitRecentGoods(recentGoods, viewMaxProducts);
                return;
            }
        }

        recentGoods.add(new RecentGoods(profile.getProfileCompositeId(), cmId, DateUtil.getDate()));
        sortedAndLimitRecentGoods(recentGoods, viewMaxProducts);
    }

    private void sortedAndLimitRecentGoods(List<RecentGoods> recentGoods, int viewMaxProducts) {
        recentGoods.sort(Comparator.comparing(RecentGoods::getDateTime).reversed());

        if (recentGoods.size() > viewMaxProducts) {
            recentGoods.subList(viewMaxProducts, recentGoods.size()).clear();
        }
    }

Он реализует следующие логи c:

  1. метод принимает профиль и идентификатор просматриваемого продукта

  2. Проверяет, просматривал ли пользователь данный товар до

  3. При просмотре обновляет дату ; если не просматривается, добавляется как просмотренное

  4. Так как магазин ограничивает размер списка просмотренных товаров, я его обрезаю

  5. Как В результате база данных содержит список последних просмотренных пользователем продуктов.

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

Наблюдаются следующие ошибки при ведении журнала:

  1. rg.hibernate.StaleStateException: Batch update вернул неожиданное количество строк из update [0]; фактическое количество строк: 0; ожидается: 1

  2. org.hibernate.StaleStateException: пакетное обновление вернуло неожиданное количество строк из обновления [0]; фактическое количество строк: 0; Ожидается: 1], SQL: удалить из view_products, где id =?

Я пытался решить ее по-разному:

   @Transactional
1. public synchronized void addRecentGoods(Profile profile, Long cmId) {...}

   @Transactional
2. public void addRecentGoods(Profile profile, Long cmId) {
synchronized (profile.getProfileCompositeId()){...} }

3. @org.springframework.transaction.annotation.Transactional(isolation = Isolation.SERIALIZABLE)
    public void addRecentGoods(Profile profile, Long cmId) {...}

   @Transactional
4. @Lock(LockModeType.PESSIMISTIC_WRITE)
    public void addRecentGoods(Profile profile, Long cmId) {...}

Эти решения не Может быть, я не правильно их применяю. Как я могу решить эту проблему?

Большое спасибо за ваше внимание.

PS Сам logi c работает правильно, а при ручном тестировании или тестировании службы отдыха работает корректно, только ошибки начать нагрузочное тестирование, когда один пользователь делает два запроса в одну секунду.

В то же время, если код написан так, как показано в Примере, только 4% тестов не проходят, и если я ставлю блокировки или что-то еще, ситуация ухудшается.

П. S Два. Вы можете видеть, что я где-то неправильно работаю с jpa, и это вызывает эту проблему. Буду благодарен за любую помощь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...