QuerySyntaxException occurred for JPA #Query for Distinct and Count - spring-boot

I am using the below as a JpaRepository interface method query
#Query("SELECT DISTINCT order.status, COUNT(*) FROM OrderEntity order WHERE order.customerNumber = ?1 GROUP BY order.status")
During app startup I am getting the following exception -
Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: order near line 1, column 17 [SELECT DISTINCT order.status AS status, COUNT(*) AS count FROM debomitra.cmw.orders.entity.OrderEntity order WHERE order.customerNumber = ?1 GROUP BY order.status]
at org.hibernate.hql.internal.ast.QuerySyntaxException.convert(QuerySyntaxException.java:74)
at org.hibernate.hql.internal.ast.ErrorTracker.throwQueryException(ErrorTracker.java:93)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.parse(QueryTranslatorImpl.java:297)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:189)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:144)
at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:113)
at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:73)
at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:155)
at org.hibernate.internal.AbstractSharedSessionContract.getQueryPlan(AbstractSharedSessionContract.java:600)
at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:709)
... 116 more
Is there any other way to write DISTINCT/COUNT query in JPA or am I doing something wrong?
Please provide me with some pointers.

I think the query will work if you modify it like below-
SELECT DISTINCT OrderEntity.status, COUNT(*) FROM OrderEntity WHERE OrderEntity.customerNumber = ?1 GROUP BY OrderEntity.status

The issue is with the order keyword in the JPQL. It is expecting a "by" keyword after the "order".
Whoever is reading this try avoiding "order" keyword in a statement expect at the end where you really need to issue a ORDER BY statement.

Related

JdbcPagingItemReader not working with join query

I have two tables table 1 and table 2. Both have same name id column.
As it's a left outer join query, I have to use aliases.
In sortKeys, If I mention id , error is
Caused by: org.postgresql.util.PSQLException: ERROR: column reference "id" is ambiguous
In sortKeys, If I mention t1.id , error is
Caused by: org.postgresql.util.PSQLException: The column name t1.id was not found in this ResultSet.
How to handle such queries?
I am using latest spring boot version 2.2.5.RELEASE
I have seen other posts related to this issue on stackoverflow. However, those are in older versions of spring batch and hence I should not face this issue.
One way you could solve this issue, is by adding the t1.id as projection and naming it something else, like :
select t1.id as id_t1 ....
and in your sortKeys add "id_t1".
Hope this helps
The answer by #youness.bout and another kind programmer worked for me. I've documented it here https://github.com/spring-projects/spring-batch/issues/1208#issuecomment-994234546. It appears to be a known issue in Spring Batch project.
Rewriting the answer here:
Using the same column name alias as that in column name in the select clause - t1.table1_column1 as 't1.table1_column1'
Enclosing the column name alias in single quote (') in the select clause - t1.table1_column1 as 't1.table1_column1'
Used the column name alias as the sort key - setSortKey("t1.table1_column1")
Here's what I did in kotlin
#Bean
#StepScope
fun readQueryProvider() = SqlPagingQueryProviderFactoryBean().apply {
setDataSource(dataSource)
setSelectClause("select t1.table1_column1 as 't1.table1_column1', t1.table1_column2,"
+ " t1.table1_column3, t2.table2_column2, t3.table3_column3")
setFromClause("table1 t1"
+ " inner join table2 t2 on t1.table1_column1 = t2.table2_column1"
+ " inner join table3 t3 on t2.table2_column2 = t3.table3_column2"
+ " inner join table4 t4 on t1.table1_column1 = t4.table4_column1")
setWhereClause("where t3.table3_column2 = :placeholder1"
+ " and t2.table2_column3 = :placeholder2 and t4.table4_column2 = :placeholder3")
setSortKey("t1.table1_column1")
}

Hibernate + Oracle Group By Results in ORA-00979: not a GROUP BY expression error

I have the following Hibernate HQL query:
select t from Term t join ApprovedCourse ap on t.id = ap.term.id group by t order by t desc
It's failing with the
ORA-00979: not a GROUP BY expression
error because Oracle insists that all select values be in the group by. Hibernate, of course, is hiding the various fields of the Term object from us, letting us deal with it as a Term and not Term.id. (This query works on Postgres, by the way. Postgres is more liberal about its group by requirements.)
Hibernate is producing the following SQL:
select term0_.id as id1_12_, term0_.semester_id as semester_id2_12_, term0_.year_id as year_id3_12_
from term term0_
inner join approved_course approvedco1_
on (term0_.id=approvedco1_.term_id)
group by term0_.id
order by term0_.id desc
I've tried just removing the select t from the start of the query, but then Hibernate assumes that I'm selecting both the Term and ApprovedCourse objects, and that makes things worse.
So how do I make this work in a Hibernate way?
I found that I could get what I want by replacing the group by clause with a distinct in the select clause. Here's the resulting query:
select distinct(t) from Term t join ApprovedCourse ap on t.id = ap.term.id order by t desc

Query syntax error on HQL Query

Hql query:
Select ecd.consumption from com.dventus.wonchi.jaxb.messages.Wonchi as w
join w.systemBound as consumption
join consumption.fixedNetwork as ecd
where w.meterId = 'DVEHighLowUsageCheck' and ecd.time in (select min(ecd.time))
Exception:
java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected end of subtree [Select ecd.consumption from com.dventus.wonchi.jaxb.messages.Wonchi as w join w.systemBound as consumption join consumption.fixedNetwork as ecd where w.meterId = 'DVEHighLowUsageCheck' and ecd.time in (select min(ecd.time))]
As pointed for #getjackx, the syntax is incorrect.
You need add the clause FROM for the subselect select min(ecd.time), like:
select min(ecd2.time) FROM FixedNetwork ec2

Issue with Spring data jpa Db2 pagination

I am using Spring JPA with DB2, when i use paging repository and queries for second page it throws error.
This is the generated query
SELECT *
FROM (SELECT inner2_.*,
ROWNUMBER()
OVER(
ORDER BY ORDER OF inner2_) AS rownumber_
FROM (SELECT db2DATAa0_.c_type AS col_0_0_,
db2DATAa0_.h_proc AS col_1_0_,
db2DATAa0_.n_vin AS col_2_0_,
db2DATAa0_.i_cust AS col_3_0_
FROM dcu.v_rpt_data_hist db2DATAa0_
WHERE db2DATAa0_.reportid = '0H000488089'
AND ( db2DATAa0_.c_type = 'S'
OR db2DATAa0_.c_type = 'N'
OR db2DATAa0_.c_type = 'A'
OR db2DATAa0_.c_type = 'T' )
ORDER BY db2DATAa0_.h_proc desc
FETCH first 30 ROWS only) AS inner2_) AS inner1_
WHERE rownumber_ > 15
ORDER BY rownumber_
Error:
2719372 [2016-10-21 16:29:02,040] [RxCachedThreadScheduler-13] WARN org.hibern
ate.engine.jdbc.spi.SqlExceptionHelper - SQL Error: -199, SQLState: 42601
2719379 [2016-10-21 16:29:02,047] [RxCachedThreadScheduler-13] ERROR org.hibern
ate.engine.jdbc.spi.SqlExceptionHelper - DB2 SQL Error: SQLCODE=-199, SQLSTATE=
42601, SQLERRMC=OF;??( [ DESC ASC NULLS RANGE CONCAT || / MICROSECONDS MICROSECO
ND, DRIVER=3.57.82
Any idea?
Your error states the ILLEGAL USE OF KEYWORD OF. TOKEN [DESC ASC NULLS RANGE CONCAT] WAS EXPECTED.
I identified this as the critical part of the query:
ORDER BY ORDER OF inner2_
DB2 expects one of DESC, ASC, NULLS, RANGE, CONCAT after the second ORDER keyword.
This issue can be resolve by change dialect.
Change dialect in configuration or property file to DB2ZOSDialect

distinct & trim in JPA with hibernate 3.2.6

Is there a way to do select distinct trim(addressInfo.city) in JPA ?
I got this error (without the trim it works fine)
Caused By: java.sql.SQLSyntaxErrorException: ORA-01791: not a SELECTed expression
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:445)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:396)
at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:879)
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:450)
at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:192)
Truncated. see log file for complete stacktrace
>
and Here the generated SQL:
select distinct trim(addressinf3_.city) as col_0_0_
from t_application applicatio0_
left outer join t_user user1_ on applicatio0_.first_signatory=user1_.id
left outer join t_company company2_ on user1_.company=company2_.id
left outer join t_address_info addressinf3_ on company2_.address=addressinf3_.id
where applicatio0_.discriminator='SERVICE' and (addressinf3_.city is not null) order by addressinf3_.city
This exception usually happens when you have some column/expression in order by clause which you don't have in select clause, in combination with distinct. Without knowing the actual JPQL query you are executing, here is an example that should work
select distinct trim(addressInfo.city)
from AddressInfo addressInfo
where <some conditions>
order by trim(addressInfo.city)
If you use trim(addressInfo.city) in select, then you must use it also in order by. Without trim it won't work.

Resources