Skip to content

FetchableFluentQueryBySpecification ignores sortBy for slice and unpaged page #4297

Description

@kmdy7991

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.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions