Spring JPA / Hibernate возвращает случайную последнюю страницу?

#java #spring-boot #hibernate #spring-data-jpa

#java #spring-boot #переход в спящий режим #spring-data-jpa

Вопрос:

Я недавно обновил сервис с:

  • JDK8 -> JDK11
  • Весенняя загрузка 1.5 -> Весенняя загрузка 2.3

С тех пор интеграционный тест странным образом завершается неудачей, так что при выполнении запроса (с возможностью просмотра страниц). Из 100 результатов, т. е. 5 страниц, 5-я страница всегда выбирается случайным образом.

Результат выглядит примерно так:

Страница 0 (идентификаторы [0, 19])

 [SomeObject@... 'inttest_log_device_0', ...]
[SomeObject@... 'inttest_log_device_1', ...]
[SomeObject@... 'inttest_log_device_2', ...]
[SomeObject@... 'inttest_log_device_3', ...]
[SomeObject@... 'inttest_log_device_4', ...]
[SomeObject@... 'inttest_log_device_5', ...]
[SomeObject@... 'inttest_log_device_6', ...]
[SomeObject@... 'inttest_log_device_7', ...]
[SomeObject@... 'inttest_log_device_8', ...]
[SomeObject@... 'inttest_log_device_9',...]
[SomeObject@... 'inttest_log_device_10', ...]
[SomeObject@... 'inttest_log_device_11', ...]
[SomeObject@... 'inttest_log_device_12', ...]
[SomeObject@... 'inttest_log_device_13', ...]
[SomeObject@... 'inttest_log_device_14', ...]
[SomeObject@... 'inttest_log_device_15', ...]
[SomeObject@... 'inttest_log_device_16', ...]
[SomeObject@... 'inttest_log_device_17', ...]
[SomeObject@... 'inttest_log_device_18', ...]
[SomeObject@... 'inttest_log_device_19', ...]
  

Страницы 1-3 продолжаются, как указано выше.

Однако последняя страница (# 4) отличается (ожидаемые идентификаторы [80, 99]) :

 [SomeObject@... 'inttest_log_device_25', ...]
[SomeObject@... 'inttest_log_device_94', ...]
[SomeObject@... 'inttest_log_device_0', ...]
[SomeObject@... 'inttest_log_device_31', ...]
[SomeObject@... 'inttest_log_device_62', ...]
[SomeObject@... 'inttest_log_device_13', ...]
[SomeObject@... 'inttest_log_device_69', ...]
[SomeObject@... 'inttest_log_device_33', ...]
[SomeObject@... 'inttest_log_device_64', ...]
[SomeObject@... 'inttest_log_device_52', ...]
[SomeObject@... 'inttest_log_device_86', ...]
[SomeObject@... 'inttest_log_device_24', ...]
[SomeObject@... 'inttest_log_device_16', ...]
[SomeObject@... 'inttest_log_device_22', ...]
[SomeObject@... 'inttest_log_device_89', ...]
[SomeObject@... 'inttest_log_device_50', ...]
[SomeObject@... 'inttest_log_device_57', ...]
[SomeObject@... 'inttest_log_device_92', ...]
[SomeObject@... 'inttest_log_device_29', ...]
[SomeObject@... 'inttest_log_device_15', ...]
  

Выполняемый код является:

 someRepository.findAll(predicate, pageable);

  

Где репозиторий просто расширяет Spring JpaRepository и QuerydslPredicateExecutor . predicate Это BooleanBuilder с некоторыми критериями фильтрации.

Кроме того, код всегда работал отлично. Проблемы начались только после обновления.

Комментарии:

1. И у вас есть явный order by (порядок сортировки) в вашем запросе? В противном случае он использует все, что возвращает база данных.

2. @M.Deinum сортировка сделала это! Большое спасибо. Если вы хотите, вы можете написать реальный ответ, и я приму его.

Ответ №1:

Без явного упорядочения вы в основном подвергаетесь риску СУБД того, что она возвращает. При использовании подкачки у вас всегда должен быть явный порядок.

Вы можете сделать это, добавив Sort к Pageable переданной вами.

 Pageable pageable = PageRequest.of(0, 1, Direction.ASC, "id);
  

Что-то подобное должно сработать.