While building a Test API, I noticed that fluent sortBy(…) is ignored in some JpaSpecificationExecutor.findBy(…) paths when the provided Pageable itself is unsorted.
Reproducer: https://github.com/kmdy7991/jpa-issue-demo
Reproduction
Slice<CustomerOrder> slice = orders.findBy(
OrderSpecs.statusIs(Status.PAID),
q -> q.sortBy(Sort.by(DESC, "createdAt"))
.slice(PageRequest.of(0, 5)));
Expected: the query uses createdAt desc from sortBy(…).
Actual: the generated SQL has no order by:
select ... from orders co1_0
where co1_0.status=?
offset ? rows fetch first ? rows only
For comparison, the equivalent page(PageRequest.of(0, 5)) path applies the sort correctly:
select ... from orders co1_0
where co1_0.status=?
order by co1_0.created_at desc
offset ? rows fetch first ? rows only
The unpaged path shows the same issue:
orders.findBy(
OrderSpecs.amountAtLeast(20_000),
q -> q.sortBy(Sort.by(DESC, "totalAmount"))
.page(Pageable.unpaged()));
Analysis
FetchableFluentQueryBySpecification uses pageable.getSort() in the affected paths, so an unsorted Pageable drops the sort configured through sortBy(…).
The Querydsl counterpart uses pageable.getSortOr(this.sort), which preserves the fluent sort when the Pageable is unsorted.
This looks related to GH-3762, which made Pageable sort override the fluent sort when present. The missing case here seems to be the fallback behavior: when the Pageable is unsorted, the fluent sortBy(…) sort should still be used. Existing tests cover the override case, but not this fallback for Specification slice(…) and unpaged terminals.
I can submit a pull request with the fix and regression tests.
While building a Test API, I noticed that fluent
sortBy(…)is ignored in someJpaSpecificationExecutor.findBy(…)paths when the providedPageableitself is unsorted.Reproducer: https://github.com/kmdy7991/jpa-issue-demo
Reproduction
Expected: the query uses createdAt desc from sortBy(…).
Actual: the generated SQL has no order by:
For comparison, the equivalent page(PageRequest.of(0, 5)) path applies the sort correctly:
The unpaged path shows the same issue:
Analysis
FetchableFluentQueryBySpecificationusespageable.getSort()in the affected paths, so an unsortedPageabledrops the sort configured throughsortBy(…).The Querydsl counterpart uses
pageable.getSortOr(this.sort), which preserves the fluent sort when thePageableis unsorted.This looks related to GH-3762, which made
Pageablesort override the fluent sort when present. The missing case here seems to be the fallback behavior: when thePageableis unsorted, the fluentsortBy(…)sort should still be used. Existing tests cover the override case, but not this fallback for Specificationslice(…)and unpaged terminals.I can submit a pull request with the fix and regression tests.