spring-data-jpa: Order by expression missing in select list after update to Spring Boot 3.0.1 with DISTINCT queries
Hi there,
Spring Boot: 3.0.1 Database: postgres 14
I am seeing an issue after updating from Spring Boot 2.7x to Spring Boot 3.0.1. I am raising this issue here as I think the issue lies within Spring Data JPA after some debugging, specifically in QueryUtils in converting a Sort to an Expression.
I provide the following Sort as a default for a query
Sort.by(Sort.Order.desc(Study_.DATE), Sort.Order.desc(Study_.TIME), Sort.Order.asc("patient.lastName"), Sort.Order.asc("patient.firstName"))
I pass this through to findAll(Specification, Sort) and the following query is generated
select
distinct s1_0.id,
s1_0.date,
s1_0.description,
s1_0.patient_id,
s1_0.size,
s1_0.study_instance_uid,
s1_0.time
from
patient.studies s1_0
join patient.patients p1_0 on p1_0.id = s1_0.patient_id
where
s1_0.customer_id = ?
order by
s1_0.date desc,
s1_0.time desc,
p1_0.last_name asc,
p1_0.first_name asc offset ? rows fetch first ? rows only
Note that this query is DISTINCT. This query will fail with PSQLException: ERROR: for SELECT DISTINCT, ORDER BY expressions must appear in select list. If I remove the distinct and run this the query will execute successfully but will give the wrong results.
If I try to work around this by using an entity graph to fetch the patient record eagerly, Spring Data will not detect the join in QueryUtils and join the record again and then use that alias in the order by, once again running into the same issue.
select
distinct s1_0.id,
s1_0.date,
s1_0.description,
p2_0.id,
p2_0.attributes_id,
p2_0.created_at,
p2_0.customer_id,
p2_0.deceased,
p2_0.deceased_at,
p2_0.deleted_at,
p2_0.dob,
p2_0.first_name,
p2_0.last_name,
p2_0.middle_name,
p2_0.prefix,
p2_0.sex,
p2_0.suffix,
p2_0.updated_at,
s1_0.size,
s1_0.study_instance_uid,
s1_0.time
from
patient.studies s1_0
join patient.patients p1_0 on p1_0.id = s1_0.patient_id
left join patient.patients p2_0 on p2_0.id = s1_0.patient_id
where
s1_0.customer_id = ?
order by
s1_0.date desc,
s1_0.time desc,
p1_0.last_name asc,
p1_0.first_name asc offset ? rows fetch first ? rows only
I think this issue is likely caused by a combination of the new aliasing in Hibernate and the related changes made to QueryUtils about 8 months ago.
From searching through Hibernate bug tracker, there are a few reports of this issue going way back to early 5.x releases of Hibernate. eg https://hibernate.atlassian.net/browse/HHH-13434. The feedback from the maintainers is a fetch() should be used rather than a join in these cases.
About this issue
- Original URL
- State: open
- Created a year ago
- Reactions: 4
- Comments: 15 (4 by maintainers)
Hi Greg,
Unfortunately it’s a complicated dynamic query, if I could have done it with @Query I certainly would have.
Basically, the only change required to make it work in Query Utils is this
The other changes are all just allowing that
isDistinctparam to be passed around up to where we have access to thequeryvariable and can getquery.isDistinct()With this change made, all the tests pass however there are a few method signatures that need to be updated to pass isDistinct through to this method.
All of our more complicated or dynamic queries are done via a Specification and we are currently having this issue in 3.1 but with this small patch its working well.