From 227111199ee579fcd9ca6ca7eef9d798b449da2c Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Mon, 23 Feb 2026 11:39:24 +0100 Subject: [PATCH] Avoid duplicate order by in derived queries. We now use primarily the Sort order provided through Sort and only fall back to Pageable.sort if Sort has not been specified. Previously, we combined the Sort from Pageable and Sort which caused duplicates as the parameter accessor emulates Pageable and Sort if either one is not specified causing duplicate information. Closes #2228 --- .../repository/query/StatementFactory.java | 6 +++- .../query/PartTreeJdbcQueryUnitTests.java | 33 +++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/query/StatementFactory.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/query/StatementFactory.java index 566a50eb2..0e6093699 100644 --- a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/query/StatementFactory.java +++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/query/StatementFactory.java @@ -145,7 +145,6 @@ public class StatementFactory { if (pageable != null) { this.pageable = pageable; - orderBy(pageable.getSort()); } return this; } @@ -202,6 +201,11 @@ public class StatementFactory { SelectBuilder.SelectOrdered selectOrderBuilder = applyCriteria(criteria, entity, table, parameterSource, whereBuilder); + Sort sort = this.sort; + if (sort.isUnsorted()) { + sort = pageable.getSort(); + } + if (mode == Mode.SLICE || mode == Mode.SELECT) { selectOrderBuilder = applyOrderBy(sort, entity, table, selectOrderBuilder); } diff --git a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/query/PartTreeJdbcQueryUnitTests.java b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/query/PartTreeJdbcQueryUnitTests.java index f9366d635..ea6204c45 100644 --- a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/query/PartTreeJdbcQueryUnitTests.java +++ b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/query/PartTreeJdbcQueryUnitTests.java @@ -31,6 +31,9 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.data.annotation.Id; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; import org.springframework.data.jdbc.core.convert.JdbcConverter; import org.springframework.data.jdbc.core.convert.MappingJdbcConverter; import org.springframework.data.jdbc.core.convert.RelationResolver; @@ -604,6 +607,32 @@ public class PartTreeJdbcQueryUnitTests { .isThrownBy(() -> jdbcQuery.createQuery(getAccessor(queryMethod, new Object[] { 1L }), returnedType)); } + @Test // GH-2228 + void createsPagedQuery() throws Exception { + + JdbcQueryMethod queryMethod = getQueryMethod("findAllByFirstName", String.class, Pageable.class); + PartTreeJdbcQuery jdbcQuery = createQuery(queryMethod); + RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, + new Object[] { "John", PageRequest.of(0, 10, Sort.by("lastModified")) }); + ParametrizedQuery query = jdbcQuery.createQuery(accessor, returnedType); + + QueryAssert.assertThat(query).containsQuotedAliasedColumns(columns) + .contains("ORDER BY \"users\".lastModified ASC OFFSET 0"); + } + + @Test // GH-2228 + void createsSortedQuery() throws Exception { + + JdbcQueryMethod queryMethod = getQueryMethod("findAllByFirstName", String.class, Sort.class); + PartTreeJdbcQuery jdbcQuery = createQuery(queryMethod); + RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, + new Object[] { "John", Sort.by("lastModified") }); + ParametrizedQuery query = jdbcQuery.createQuery(accessor, returnedType); + + QueryAssert.assertThat(query).containsQuotedAliasedColumns(columns); + assertThat(query.getQuery()).endsWith("ORDER BY \"users\".lastModified ASC"); + } + @Test // DATAJDBC-318 void throwsExceptionWhenConditionKeywordIsUnsupported() throws Exception { @@ -783,6 +812,10 @@ public class PartTreeJdbcQueryUnitTests { List findAllByFirstNameIgnoreCase(String firstName); + List findAllByFirstName(String firstName, Pageable pageable); + + List findAllByFirstName(String firstName, Sort sort); + User findByIdIgnoringCase(Long id); List findAllByIdIsEmpty();