diff --git a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/JSqlParserQueryEnhancer.java b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/JSqlParserQueryEnhancer.java index 654d1df20..57f547a06 100644 --- a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/JSqlParserQueryEnhancer.java +++ b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/JSqlParserQueryEnhancer.java @@ -501,6 +501,15 @@ public class JSqlParserQueryEnhancer implements QueryEnhancer { : property; Expression orderExpression = order.isIgnoreCase() ? getJSqlLower(reference) : new Column(reference); orderByElement.setExpression(orderExpression); + + switch (order.getNullHandling()) { + case NULLS_FIRST -> orderByElement.setNullOrdering(OrderByElement.NullOrdering.NULLS_FIRST); + case NULLS_LAST -> orderByElement.setNullOrdering(OrderByElement.NullOrdering.NULLS_LAST); + default -> { + // do nothing + } + } + return orderByElement; } diff --git a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/JSqlParserQueryEnhancerUnitTests.java b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/JSqlParserQueryEnhancerUnitTests.java index e0be59508..96411755f 100644 --- a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/JSqlParserQueryEnhancerUnitTests.java +++ b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/JSqlParserQueryEnhancerUnitTests.java @@ -25,6 +25,8 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import org.springframework.data.domain.Sort; +import org.springframework.data.projection.SpelAwareProxyProjectionFactory; +import org.springframework.data.repository.query.ReturnedType; /** * TCK Tests for {@link JSqlParserQueryEnhancer}. @@ -51,6 +53,19 @@ class JSqlParserQueryEnhancerUnitTests extends QueryEnhancerTckTests { assertThat(sql).isEqualTo("SELECT e FROM Employee e ORDER BY e.foo ASC, e.bar ASC"); } + @Test // GH-3886 + void shouldApplySortingWithNullsPrecedence() { + + QueryEnhancer enhancer = createQueryEnhancer(DeclaredQuery.of("SELECT e FROM Employee e", true)); + + String sql = enhancer.rewrite(new DefaultQueryRewriteInformation( + Sort.by(Sort.Order.asc("foo").with(Sort.NullHandling.NULLS_LAST), + Sort.Order.desc("bar").with(Sort.NullHandling.NULLS_FIRST)), + ReturnedType.of(Object.class, Object.class, new SpelAwareProxyProjectionFactory()))); + + assertThat(sql).isEqualTo("SELECT e FROM Employee e ORDER BY e.foo ASC NULLS LAST, e.bar DESC NULLS FIRST"); + } + @Test // GH-3707 void countQueriesShouldConsiderPrimaryTableAlias() {