简体   繁体   中英

Spring Data JPA Specifications - Distinct + order by column in join

I have some specifications that I am combining with "and":

Specification.where(predicate1).and(predicate2).and(predicate3);

One of them has distinct set:

query.distinct(true);

Another one makes an order by on a column that is in a join.

query.orderBy(builder.desc(bJoin.get("orderbyColumn")));

This fails with a SQLGrammarException stating that order by column should be in distinct.

So basically we have entity A, the main entity, and some nested entity B, we select from A but want to order by B, and in generated sql it only selects columns from A. The only way I found to make it work (= making it select from B as well) is to replace the join by a fetch:

Fetch < A, B > bFetch = root.fetch("joinCol", JoinType.INNER);
Join < A, B > bJoin = (Join < A, B > ) bFetch;

that worked for some time, was testing locally in H2, but then after some time started getting another error:

org.hibernate.QueryException: query specified join fetching, but the owner of the fetched association was not present in the select list

I solved it somehow in my local pointing to H2 by requiring some columns to not be null, but in real server using PostgreSQL, it's not working at all, getting that error for all cases when a fetch is present.

My question is: what is the right way to use distinct along with orderby on a nested entity that is not fetched? Is my solution with fetch ok and it just needs to be fixed (and if so how?) or I should go for another option entirely?

For the actual query I am using this method:

findAll(Specification<>, Pageable)

Isn't there a way to have distinct wrapping the whole query with order by (some sort of subquery?) and bypassing all this nightmare? Have it generate a query like this:

select distinct colA1, colA2, coAl3 from (select colA1, colA2, coAl3 

from A inner join B b on ........ order by b.colB1)

Do I need to convert my specification to predicate manually and do something else with it to try to solve my issues (some kind of hybrid approach)?

Any pieces of advice will be greatly appreciated.

I encountered same error but actually it was not error:)

findAll(Specification<>, Pageable) this method throws 2 different queries.

First one is count query where you have to be careful. Second is the rows query where you actually did it.

You can check the query type with code below

if (query.getResultType() != Long.class && query.getResultType() != long.class){
   root.fetch("entity1");
} 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM