У меня есть проблема, которую я не могу решить и, возможно, не совсем понимаю. Я буду благодарен за любую помощь.
У меня есть код:
@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:
метод принимает профиль и идентификатор просматриваемого продукта
Проверяет, просматривал ли пользователь данный товар до
При просмотре обновляет дату ; если не просматривается, добавляется как просмотренное
Так как магазин ограничивает размер списка просмотренных товаров, я его обрезаю
Как В результате база данных содержит список последних просмотренных пользователем продуктов.
Проблемы начинаются, когда мы тестируем случай, если пользователь нажимает кнопку несколько раз очень быстро и работа начинается в В многопоточной среде два потока начинают изменять один и тот же список просматриваемых продуктов.
Наблюдаются следующие ошибки при ведении журнала:
rg.hibernate.StaleStateException: Batch update вернул неожиданное количество строк из update [0]; фактическое количество строк: 0; ожидается: 1
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, и это вызывает эту проблему. Буду благодарен за любую помощь.