Description
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.