Hibernate GROUP BY invalid for Oracle - java

I created an Hibernate query like this:
select new ProjectForUser
(p.projectId, p.name, p.description, p.client, p.startDate, p.endDate,
p.liveDate, p.projectState, p.overallRagStatus, p.scopeRagStatus, p.flt,
up.projectManager)
from UserProjectAssociation up left join up.project p
where up.user.id = :userId and up.project.projectState != 'ARCHIVED'
group by p.projectId
to retrieve projects for user. Projects are stored in one table, users in the other and UserProjectAssociation is a joining table with additional attribute - projectManager.
The whole query works fine for H2 database, but on oracle I get this error:
ORA-00979: not a GROUP BY expression
What is a correct way to use GROUP BY for Oracle?
Thanks!

The Problem. ORA-00979 occurs when the GROUP BY clause does not contain all the expressions in the SELECT clause. Any SELECT expression that is not included in the GROUP function must be listed in the GROUP BY clause. These are AVG, COUNT, MAX, MIN, SUM, STDDEV, and VARIANCE.
see: https://www.tekstream.com/resources/ora-00979-not-a-group-by-expression/

Related

Spring Data JPA - count number or results of query

I want to get the number of results of a query in Spring Data Jpa, using a non-native #Query method. It consists of a basic group by plus a having clause.
My plain query looks like this (analogous example):
select count(*) from (
select 1 from table t
where t.field_a = 1
group by t.id
having count(*) = 2) a;
Since Hibernate 5 does not allow subqueries in the form clause, I have to find a workaround for that. The only one I found is very inefficient as per the query plan:
select count(*) from table t
where t.field_a = 1 and
2 = (select count(*) from table temp where temp.id = t.id);
Is there a way to write a Spring Data JPA query that's as efficient as the first one? I can think of no solution rather than selecting the inner query and taking its size() in java, but that can produce issues due to a ton of redundant data passing through the network.
There is no easy solution to count the results of a subquery in JPA but the a workaround is proposed here https://arjan-tijms.omnifaces.org/2012/06/counting-rows-returned-from-jpa-query.html.
The principle is to build a native query based on the initial Jpa subselect query.
This does the job if you accept to count the elements in java !
Query q = em.createQuery(
"select 1 from table t where field_a = 1 " +
"group by t.id having count(*) = 2");
int count = q.getResultList().size();
(performances depending on the number of lines returned, but the projection is very light : 1)

How to avoid duplicating a function call in this JPA/JPQL query?

I have the following JPA query that truncates dates to a full hour and counts them:
SELECT a.alertconfiguration.id.id,
date_trunc('hour', a.date) AS fromDate,
count(*) AS count
FROM alert a
GROUP BY a.alertconfiguration.id.id,
a.alertlevel,
date_trunc('hour', a.date)
I'm running this in a Spring Boot application using Hibernate. It works fine. But I don't want to duplicate the function call to date_trunc.
I have tried referring to fromDate in the GROUP BY clause but then I get an exception org.postgresql.util.PSQLException: ERROR: column "fromdate" does not exist
http://hibernate.atlassian.net/browse/HHH-9301 also states it is not possible to refer to aliases in the group by clause.
How could I rewrite my query without the duplicate function call?
Can you give a try using 2 instead of date_trunc('hour', a.date) in group by clause, as fromdate is 2nd column
Hibernate does not work with alias in group by or any aggregate functions. And as you will see in your sql query generated, the alias is different than that you have assigned.

Expression not in aggregate or GROUP BY columns Exception

I have a table in MS-Access database named ItemRates which contains columns ItemID, ItemName, TotalFeet, RatePerItem, TotalRate and this database is connected with my java application.
When i run the following query
String sql = "SELECT SUM(TotalRate) AS ItemRateSum, TotalFeet FROM ItemRates";
I get the following exception
net.ucanaccess.jdbc.UcanaccessSQLException: UCAExc:::3.0.7 expression not in aggregate or
GROUP BY columns: PUBLIC.ITEMRATES.TOTALFEET
I have seen other questions related to this exception on StackOverflow and one accepted answer suggested to add GroupBy clause at the end of the query. I added a GroupBy clause
String sql = "SELECT SUM(TotalRate) AS ItemRateSum, TotalFeet FROM
ItemRates GROUPBY ItemName";
and i got almost same exception (there's a slight difference between two exceptions at the end after the colon)
net.ucanaccess.jdbc.UcanaccessSQLException: UCAExc:::3.0.7 expression not in aggregate or
GROUP BY columns: GROUPBY.TOTALFEET
What am i doing wrong here ?
The correct syntax is:
SELECT SUM(TotalRate) AS ItemRateSum, TotalFeet
FROM ItemRates
GROUP BY TotalFeet;
That is, TotalFeet is not an argument to an aggregation function, so it needs to be in the GROUP BY.
All columns which are selected and are not part of the aggregate functions have to be included in the group by clause

Hibernate exception on encountering mysql := operator

When I execute the following code the exception occurs:
Exception: org.springframework.orm.hibernate3.HibernateQueryException:
Not all named parameters have been set
Here is my code:
queryString = SET #quot=0,#latest=0,#comp='';
select B.* from (
select A.time,A.change,IF(#comp<>A.company,1,0) as LATEST,#comp:=A.company as company from (
select time,company,quote-#quot as `change`, #quot:=quote curr_quote
from stocks order by company,time) A
order by company,time desc) B where B.LATEST=1;
list = getHibernateTemplate().executeFind(new HibernateCallback(){
public Object doInHibernate(Session session)throws HibernateException,SQLException {
SQLQuery query = session.createSQLQuery(queryString);
query.setParameterList("list", custIds);
return query.list();
}
What is the reason for this behavior?
It's a little bit hard to understand, what is exactly the query you are executing, but if you need to use the colon character in native query, in your case as "assign a value" operator, you should escape all the colon occurances with \\ in your java String with the query, so it could be like:
select B.* from (
select A.time,A.change,IF(#comp<>A.company,1,0) as LATEST,#comp\\:=A.company as company from (
select time,company,quote-#quot as `change`, #quot\\:=quote curr_quote
from stocks order by company,time) A
order by company,time desc) B where B.LATEST=1;
Update: seems, it is not possible yet to escape the colons in Hibernate native queries, there is an open issue about it. That means, that you are not able to use a colons in Hibernate native queries not for the named parameters. You can try to create a function and call it instead of calling a query.
you can create a named query and then use it in spring jpa repository or hibernate. This link helped me from similar problem.

Hibernate 2 with MSSQL for ORDER BY

I have been working with Oracle and Postgre and recently switched to MS SQL 2012.
I use hibernate in my application and wherever I have used the Order by Criteria:
(criteria.addOrder(Order.asc("applicationId")));
It causes an error saying:
aggregate functions dont work.
Once I comment that line out my program works and data can be retrieved.
I'm using Hibernate 3.
Is there any way to order it through hibernate without this error?
edit..
This is one error I get,
Column "SKY.tcrent.RENTNO" is invalid in the ORDER BY clause because
it is not contained in either an aggregate function or the GROUP BY
clause.
Edit 2..
MY query
Query tcSchaduleQ = getSession().createQuery("SELECT SUM(tcs.dueAmount) FROM TrialCalculationSchedule tcs WHERE tcs.facilityId=:facilityId AND tcs.rentalNumber>:rentalNumber AND tcs.dueDate>:dueDate AND dueTypeId IN(:dueTypeId) ORDER BY tcs.rentalNumber ").setInteger("rentalNumber", facility.getPeriod() - noOfprePayments).setInteger("facilityId",facility.getFacilityId()).setDate("dueDate", date).setParameterList("dueTypeId", plist);
Number tcsAmt = (Number) tcSchaduleQ.uniqueResult();
and this is what hibernate generates in HQL
SELECT
SUM(tcs.dueAmount)
FROM
TrialCalculationSchedule tcs
WHERE
tcs.facilityId=:facilityId
AND tcs.rentalNumber>:rentalNumber
AND tcs.dueDate>:dueDate
AND dueTypeId IN(
:dueTypeId
)
ORDER BY
tcs.rentalNumber
and this is the SQL
select
SUM(trialcalcu0_.DUEAMT) as col_0_0_
from
SKYBANKSLFHP.tcrent trialcalcu0_
where
trialcalcu0_.FACID=?
and trialcalcu0_.RENTNO>?
and trialcalcu0_.DUEDATE>?
and (
trialcalcu0_.DUETYPEID in (
? , ?
)
)
order by
trialcalcu0_.RENTNO
Look Like you mix aggregate and non-aggregate expressions .If you are using any aggregate function like AVG() in Select query with some other non-aggregate then you must use Group By ..
Try something like this
createQuery("SELECT SUM(tcs.dueAmount) As DueAmount ...
If you are using Criteria then it should be like this
Criteria crit = sess.createCriteria(Insurance.class);
ProjectionList proList = Projections.projectionList();
proList.add(Projections.sum("investementAmount"));
crit.setProjection(proList);
List sumResult = crit.list();

Categories