Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Support NULLS {FIRST | LAST} in JPQL queries #3529

Closed
wants to merge 2 commits into from
Closed

Conversation

christophstrobl
Copy link
Member

This PR adds support for parsing and appending order by items that define a NULL precedence.
Supporting NULL precedence for Specifications and the Criteria API needs to be done separately.

Related to: #1280

This commit adds support for parsing and appending order by items that define a NULL precedence.
@mp911de mp911de self-assigned this Aug 21, 2024
@mp911de mp911de added the type: enhancement A general enhancement label Aug 21, 2024
@mp911de mp911de linked an issue Aug 21, 2024 that may be closed by this pull request
@mp911de mp911de changed the title Support NULLS {FIRST | LAST} in JPQL queries. Support NULLS {FIRST | LAST} in JPQL queries Aug 21, 2024
@mp911de mp911de marked this pull request as ready for review August 21, 2024 13:09
@mp911de mp911de closed this in 410152a Aug 21, 2024
mp911de added a commit that referenced this pull request Aug 21, 2024
Use structured NullsPrecedence rendering in JPQL renderer.

Throw UnsupportedOperationException for the time being until Nulls Precedence is supported through Criteria API.

See #3529
@mp911de mp911de added this to the 3.4 M1 (2024.1.0) milestone Aug 21, 2024
@kctang
Copy link

kctang commented Dec 5, 2024

Hi @mp911de ,

https://github.com/spring-projects/spring-data-jpa/blame/7f13a04c414ad210e30ef647fda75590e28526cb/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/QueryUtils.java#L756

I am getting "Applying Null Precedence using Criteria Queries is not yet supported." with 3.4.0.

Is this Null Precedence using Criteria Queries supported yet? If so, can we remove the conditional throw?

This is kind of blocking my app's migration from Spring Boot 2.7 to Spring Boot 3.4. FYI, when i switch to Spring Boot 3.3.6, the migrated app works.

Thanks for reading my message & hope to get a solution soon.

@mp911de
Copy link
Member

mp911de commented Dec 6, 2024

Null Precedence using Criteria Queries

Null Precedence using Criteria Query is specified with JPA 3.2 (https://jakarta.ee/specifications/persistence/3.2/). Before that, we cannot set null precedence through the API. Spring Data JPA 4.0 will be based on JPA 3.2

@kctang
Copy link

kctang commented Dec 6, 2024

Since Spring Data JPA 4.0 will be based on JPA 3.2, why do we throw "unsupported operation exception" from Spring Data JPA 3.4 (as it only needs to support JPA 3.1)? "Null Precedence using Criteria Query" is not a specified feature in prior JPA versions.

What is the impact of not having this exception check in Spring Data JPA 3.4? If there's no runtime errors, I would recommend not having this conditional exception check.

From my tests, without exception check (in Spring Data v3.3), my app's repository queries seems to be working.

Artur- added a commit to vaadin/hilla that referenced this pull request Dec 16, 2024
Without this, I see an exception for all sort requests
```
Caused by: java.lang.UnsupportedOperationException: Applying Null Precedence using Criteria Queries is not yet supported.
	at org.springframework.data.jpa.repository.query.QueryUtils.toJpaOrder(QueryUtils.java:757) ~[spring-data-jpa-3.4.0.jar:3.4.0]
	at org.springframework.data.jpa.repository.query.QueryUtils.toOrders(QueryUtils.java:706) ~[spring-data-jpa-3.4.0.jar:3.4.0]
	at org.springframework.data.jpa.repository.support.SimpleJpaRepository.getQuery(SimpleJpaRepository.java:756) ~[spring-data-jpa-3.4.0.jar:3.4.0]
	at org.springframework.data.jpa.repository.support.SimpleJpaRepository.getQuery(SimpleJpaRepository.java:714) ~[spring-data-jpa-3.4.0.jar:3.4.0]
	at org.springframework.data.jpa.repository.support.SimpleJpaRepository.findAll(SimpleJpaRepository.java:448) ~[spring-data-jpa-3.4.0.jar:3.4.0]
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[na:na]
	at java.base/java.lang.reflect.Method.invoke(Method.java:580) ~[na:na]
	at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:359) ~[spring-aop-6.2.0.jar:6.2.0]
	at org.springframework.data.repository.core.support.RepositoryMethodInvoker$RepositoryFragmentMethodInvoker.lambda$new$0(RepositoryMethodInvoker.java:277) ~[spring-data-commons-3.4.0.jar:3.4.0]
	at org.springframework.data.repository.core.support.RepositoryMethodInvoker.doInvoke(RepositoryMethodInvoker.java:170) ~[spring-data-commons-3.4.0.jar:3.4.0]
	at org.springframework.data.repository.core.support.RepositoryMethodInvoker.invoke(RepositoryMethodInvoker.java:158) ~[spring-data-commons-3.4.0.jar:3.4.0]
	at org.springframework.data.repository.core.support.RepositoryComposition$RepositoryFragments.invoke(RepositoryComposition.java:515) ~[spring-data-commons-3.4.0.jar:3.4.0]
	at org.springframework.data.repository.core.support.RepositoryComposition.invoke(RepositoryComposition.java:284) ~[spring-data-commons-3.4.0.jar:3.4.0]
	at org.springframework.data.repository.core.support.RepositoryFactorySupport$ImplementationMethodExecutionInterceptor.invoke(RepositoryFactorySupport.java:752) ~[spring-data-commons-3.4.0.jar:3.4.0]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.2.0.jar:6.2.0]
	at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:174) ~[spring-data-commons-3.4.0.jar:3.4.0]
	at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:149) ~[spring-data-commons-3.4.0.jar:3.4.0]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.2.0.jar:6.2.0]
	at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:69) ~[spring-data-commons-3.4.0.jar:3.4.0]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.2.0.jar:6.2.0]
	at org.springframewo
```

Related to spring-projects/spring-data-jpa#3529
vaadin-bot pushed a commit to vaadin/hilla that referenced this pull request Dec 16, 2024
Without this, I see an exception for all sort requests
```
Caused by: java.lang.UnsupportedOperationException: Applying Null Precedence using Criteria Queries is not yet supported.
	at org.springframework.data.jpa.repository.query.QueryUtils.toJpaOrder(QueryUtils.java:757) ~[spring-data-jpa-3.4.0.jar:3.4.0]
	at org.springframework.data.jpa.repository.query.QueryUtils.toOrders(QueryUtils.java:706) ~[spring-data-jpa-3.4.0.jar:3.4.0]
	at org.springframework.data.jpa.repository.support.SimpleJpaRepository.getQuery(SimpleJpaRepository.java:756) ~[spring-data-jpa-3.4.0.jar:3.4.0]
	at org.springframework.data.jpa.repository.support.SimpleJpaRepository.getQuery(SimpleJpaRepository.java:714) ~[spring-data-jpa-3.4.0.jar:3.4.0]
	at org.springframework.data.jpa.repository.support.SimpleJpaRepository.findAll(SimpleJpaRepository.java:448) ~[spring-data-jpa-3.4.0.jar:3.4.0]
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[na:na]
	at java.base/java.lang.reflect.Method.invoke(Method.java:580) ~[na:na]
	at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:359) ~[spring-aop-6.2.0.jar:6.2.0]
	at org.springframework.data.repository.core.support.RepositoryMethodInvoker$RepositoryFragmentMethodInvoker.lambda$new$0(RepositoryMethodInvoker.java:277) ~[spring-data-commons-3.4.0.jar:3.4.0]
	at org.springframework.data.repository.core.support.RepositoryMethodInvoker.doInvoke(RepositoryMethodInvoker.java:170) ~[spring-data-commons-3.4.0.jar:3.4.0]
	at org.springframework.data.repository.core.support.RepositoryMethodInvoker.invoke(RepositoryMethodInvoker.java:158) ~[spring-data-commons-3.4.0.jar:3.4.0]
	at org.springframework.data.repository.core.support.RepositoryComposition$RepositoryFragments.invoke(RepositoryComposition.java:515) ~[spring-data-commons-3.4.0.jar:3.4.0]
	at org.springframework.data.repository.core.support.RepositoryComposition.invoke(RepositoryComposition.java:284) ~[spring-data-commons-3.4.0.jar:3.4.0]
	at org.springframework.data.repository.core.support.RepositoryFactorySupport$ImplementationMethodExecutionInterceptor.invoke(RepositoryFactorySupport.java:752) ~[spring-data-commons-3.4.0.jar:3.4.0]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.2.0.jar:6.2.0]
	at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:174) ~[spring-data-commons-3.4.0.jar:3.4.0]
	at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:149) ~[spring-data-commons-3.4.0.jar:3.4.0]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.2.0.jar:6.2.0]
	at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:69) ~[spring-data-commons-3.4.0.jar:3.4.0]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.2.0.jar:6.2.0]
	at org.springframewo
```

Related to spring-projects/spring-data-jpa#3529
platosha pushed a commit to vaadin/hilla that referenced this pull request Dec 16, 2024
fix: set NullHandling to native when sorting (#2999)

Without this, I see an exception for all sort requests
```
Caused by: java.lang.UnsupportedOperationException: Applying Null Precedence using Criteria Queries is not yet supported.
	at org.springframework.data.jpa.repository.query.QueryUtils.toJpaOrder(QueryUtils.java:757) ~[spring-data-jpa-3.4.0.jar:3.4.0]
	at org.springframework.data.jpa.repository.query.QueryUtils.toOrders(QueryUtils.java:706) ~[spring-data-jpa-3.4.0.jar:3.4.0]
	at org.springframework.data.jpa.repository.support.SimpleJpaRepository.getQuery(SimpleJpaRepository.java:756) ~[spring-data-jpa-3.4.0.jar:3.4.0]
	at org.springframework.data.jpa.repository.support.SimpleJpaRepository.getQuery(SimpleJpaRepository.java:714) ~[spring-data-jpa-3.4.0.jar:3.4.0]
	at org.springframework.data.jpa.repository.support.SimpleJpaRepository.findAll(SimpleJpaRepository.java:448) ~[spring-data-jpa-3.4.0.jar:3.4.0]
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[na:na]
	at java.base/java.lang.reflect.Method.invoke(Method.java:580) ~[na:na]
	at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:359) ~[spring-aop-6.2.0.jar:6.2.0]
	at org.springframework.data.repository.core.support.RepositoryMethodInvoker$RepositoryFragmentMethodInvoker.lambda$new$0(RepositoryMethodInvoker.java:277) ~[spring-data-commons-3.4.0.jar:3.4.0]
	at org.springframework.data.repository.core.support.RepositoryMethodInvoker.doInvoke(RepositoryMethodInvoker.java:170) ~[spring-data-commons-3.4.0.jar:3.4.0]
	at org.springframework.data.repository.core.support.RepositoryMethodInvoker.invoke(RepositoryMethodInvoker.java:158) ~[spring-data-commons-3.4.0.jar:3.4.0]
	at org.springframework.data.repository.core.support.RepositoryComposition$RepositoryFragments.invoke(RepositoryComposition.java:515) ~[spring-data-commons-3.4.0.jar:3.4.0]
	at org.springframework.data.repository.core.support.RepositoryComposition.invoke(RepositoryComposition.java:284) ~[spring-data-commons-3.4.0.jar:3.4.0]
	at org.springframework.data.repository.core.support.RepositoryFactorySupport$ImplementationMethodExecutionInterceptor.invoke(RepositoryFactorySupport.java:752) ~[spring-data-commons-3.4.0.jar:3.4.0]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.2.0.jar:6.2.0]
	at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:174) ~[spring-data-commons-3.4.0.jar:3.4.0]
	at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:149) ~[spring-data-commons-3.4.0.jar:3.4.0]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.2.0.jar:6.2.0]
	at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:69) ~[spring-data-commons-3.4.0.jar:3.4.0]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.2.0.jar:6.2.0]
	at org.springframewo
```

Related to spring-projects/spring-data-jpa#3529

Co-authored-by: Artur <artur@vaadin.com>
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
type: enhancement A general enhancement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Consider NULLS precedence using Sort
3 participants