-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Projection fails when using subquery [DATAJPA-1713] #2008
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Jens Schauder commented Thanks for raising the issue. Based on your reproducer I was able to add a test demonstrating the issue. I haven't checked, but I assume this is due to the parser not being able to properly handle the subselect and therefore thinking the select returns single fields. This might actually be a valid workaround: instead of returning an entity: return the fields of the entity required for the projection. |
Manu VIDAL commented Ok, thanks Jens Schauder for your quick response. I'v tested this Query : I've however another problem : if I have a nested projection, i.e. a @onetomany Set property on class Employee, and a List getDepartments() in EmployeeProjection, how can I write my Query ? I point out that it works if Thanks |
Jens Schauder commented If you want to create a complex object from a SQL query with JPA, you have to use ResultSet mapping. https://thoughts-on-java.org/result-set-mapping-basics/ |
Manu VIDAL commented Sorry Jens Schauder I think I expressed myself poorly. I've added a second project demo2.zip to illustrate my test case. First method of repository works fine and retrieves 1 employee and its 2 jobs. Second method retrieves bad type and wrong numbers of results. So ... is there a workaround for this precise case ? Thanks again for your help |
Likewise, seeing something similar when using a Postgres jsonb function to try and render a jsonb array of objects as a list of entity types, e,g... @Query(
nativeQuery = true,
value = """
SELECT
x.path,
x.base64
FROM
claim c,
jsonb_to_recordset(c.files) as x(path varchar, base64 varchar)
WHERE c.id = :id
""")
List<SupportFile> findFiles(@RequestParam UUID id); |
If this involves native queries and JSONB functions on the database provider, this may have gone into something too complex for Spring Data JPA to support. Your best best moving forward may be to implement a custom implementation. Check out https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.custom-implementations for more details on how to hook such a solution into your repository. |
The original reporter on this ticket had a problem with: @Query("select c from Employee c where c.salary >= (select avg(salary) from Employee )")
List<EmployeeProjection> findProjections(); This is non-native query that involves a subselect and projections. @schauder coded a simple reproducer of the same issue that fits into our existing test machinery: // DATAJPA-1713
@Query("select u from User u where firstname >= (select Min(u0.firstname) from User u0 )")
List<NameOnly> findProjectionBySubselect();
@Test // DATAJPA-1713
public void selectProjectionWithSubselect() {
List<UserRepository.NameOnly> list = userRepository.findProjectionBySubselect();
assertThat(list).isNotEmpty() //
.allSatisfy(no -> {
assertThat(no.getFirstname()).describedAs("firstname").isNotNull();
assertThat(no.getLastname()).describedAs("lastname").isNotNull();
});
} This test scenario is overcome by the new query parser and passes. NOTE: This ticket was closed due to an unrelated native query, for which the query parser does NOT get applied, so that's why it's reopened. |
Manu VIDAL opened DATAJPA-1713 and commented
When using a subquery in query defined with
@Query
, JPA projection fails.Return type is not of projection class but
org.springframework.data.jpa.repository.query.AbstractJpaQuery$TupleConverter$TupleBackedMap**
Example :
Projection class :
Repo :
When using condition "c.salary >= 500", method returns a correct result, i.e. a List<EmployeeProjection>.
But when using a subquery "c.salary >= (select avg(salary) from Employee)", method returns a list of AbstractJpaQuery$TupleConverter$TupleBackedMap.
On this object, calling any getter returns null.
Using
@Value
(open projection) throws an exception.Example sources are attached.
Thanks in advance.
Affects: 2.2.6 (Moore SR6)
Attachments:
Referenced from: pull request #420
The text was updated successfully, but these errors were encountered: