-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 6 posts ] 
Author Message
 Post subject: JPA Criteria with SELECT DISTINCT, ORDER BY, and CONCAT
PostPosted: Wed Mar 08, 2017 12:43 am 
Newbie

Joined: Wed Feb 22, 2017 4:35 pm
Posts: 19
I'm using Hibernate 5.2.8 with Postgres. I need to order query results by way of a field selection that is a concat of a bunch of other varchars fields. I'm getting the following error:

ERROR: for SELECT DISTINCT, ORDER BY expressions must appear in select list

The weird thing is, the actual SQL generated, which wound up just doing the concat both in selection as well as the ORDER BY, is completely valid and accepted by postgres if I run it myself.. so it seems to be Hibernate that's being picky.

Adding the expression to my selection (a multiselect) results in the same error message, with functional SQL still being generated.

Creating an alias for the selected expression simply creates an alias in the select statement that is never used in the sql's ORDER BY.

There is a new bug open for something that seems similar to this. purported to be fixed in Hibernate 6:
https://hibernate.atlassian.net/browse/HHH-11504

So I'm scratching my head as to what exactly I can do to order by this field in the meantime, any ideas?


Top
 Profile  
 
 Post subject: Re: JPA Criteria: SELECT DISTINCT w/ ORDER BY aliased fields
PostPosted: Wed Mar 08, 2017 6:15 am 
Hibernate Team
Hibernate Team

Joined: Thu Sep 11, 2014 2:50 am
Posts: 1628
Location: Romania
First, we need to see the JPQL query you are using, as well as the SQL query that is generated by Hibernate.

The exception is thrown by PostgreSQL, not be Hibernate, and it's because the ORDER BY cannot use a column that was not previously selected since the SELECT stage is executed before the ORDER BY one.

Check out this great post from Lukas Eder for more details.


Top
 Profile  
 
 Post subject: Re: JPA Criteria with SELECT DISTINCT, ORDER BY, and CONCAT
PostPosted: Wed Mar 08, 2017 2:39 pm 
Newbie

Joined: Wed Feb 22, 2017 4:35 pm
Posts: 19
I read that article--I do understand the ordering of operations, but I don't understand why or how postgres is complaining when the SQL that is being generated is SQL that postgres itself will run. Furthermore, I'm pretty sure that ordering by an alias is entirely doable in JPQL.. so I'm not sure why it's choking here. I'm actually using the JPA criteria API to do this.


Here's a test case that should summarize my situation:
There are persons, and each Person has Stuff, which is their own local version of other Things.
peoples' Stuff is one to many to Things. I need to count the distinct things based on some other predicates, while ordering by the peoples' names. So essentially I'm selecting from table A based on an ordering of fields from table C (through table B, stuff).


Code:
CREATE TABLE thing (
   id serial PRIMARY KEY
);

CREATE TABLE person (
   id serial PRIMARY KEY,
   first_name varchar(255),
   last_name varchar(255),
   username varchar(255)
);

CREATE TABLE stuff (
   id serial PRIMARY KEY,
   thing_id int NOT NULL CONSTRAINT "stuff+thing.fk" REFERENCES thing(id) ON DELETE CASCADE,
   person_id int NOT NULL CONSTRAINT "stuff+person.fk" REFERENCES person(id) ON DELETE CASCADE
);




This is how I'm doing the query:

Quote:
em.createQuery( q.multiselect(thing, person, sortExp) // sortExp being the expression equivalent to the case statements above
.where(predicates)
.distinct(true)
.orderBy(cb.asc(sortExp)))



The SQL generated is roughly:

Code:
select distinct thing.id,
case
when (person.first_name is null) and (person.last_name is null) then lower(person.username)
when (person.first_name is not null) and (person.last_name is not null) then lower(((person.first_name||'')||person.last_name))
else lower(coalesce(person.first_name, person.last_name)) end as col_3_0_

from thing
left outer join stuff on thing.id=stuff.thing_id
left outer join person on stuff.person_id=person.id
order by
case
when (person.first_name is null) and (person.last_name is null) then lower(person.username)
when (person.first_name is not null) and (person.last_name is not null) then lower(((person.first_name||'')||person.last_name))
else lower(coalesce(person.first_name, person.last_name)) end
desc





If the generated SQL just used the alias col_3_0_ that it's provided.. instead of re-creating the whole case... I'm pretty sure this would function fine. Again, this query works in postgres CLI, so I have no idea why postgres is complaining about it.

This definitely is postgres choking, though I wish I knew why the postgres that hibernate is using acts differently than my CLI postgres. I'm using postgres 9.3.4.


Top
 Profile  
 
 Post subject: Re: JPA Criteria with SELECT DISTINCT, ORDER BY, and CONCAT
PostPosted: Wed Mar 08, 2017 5:39 pm 
Newbie

Joined: Wed Feb 22, 2017 4:35 pm
Posts: 19
Also, I've tried the exact same query through JDBC.... and it works. So there's something different about how hibernate is talking to postgres VS my running commands through CLI or how JDBC is talking to it. Are there any DataSource PoolProperties, or hibernate config properties that could affect this behavior of a query being rejected when hibernate sends it to postgres?


Top
 Profile  
 
 Post subject: Re: JPA Criteria with SELECT DISTINCT, ORDER BY, and CONCAT
PostPosted: Wed Mar 08, 2017 9:08 pm 
Newbie

Joined: Wed Feb 22, 2017 4:35 pm
Posts: 19
Happy to say that, after some ridiculous google acrobatics, I've figured out a workaround thanks to this guy's git commit in some unrelated file:

https://github.com/xwiki/xwiki-platform ... 575a285a89

Code:
.orderBy( cb.asc(cb.literal(5)))


... 5 being the multiselect number for the sort expression. brilliant!


Top
 Profile  
 
 Post subject: Re: JPA Criteria with SELECT DISTINCT, ORDER BY, and CONCAT
PostPosted: Thu Mar 09, 2017 2:17 am 
Hibernate Team
Hibernate Team

Joined: Thu Sep 11, 2014 2:50 am
Posts: 1628
Location: Romania
I'm glad you found the solution. The ORDER BY ordinal is a good trick.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 6 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.