sql to hql throwing exception - java

I'm using hibernate in my project and I'm trying to convert an existing sql query from DaoImplementation class to hql,
The sql query I have is
JdbcTemplate select = new JdbcTemplate(dataSource);
String sql = "SELECT * FROM (SELECT site_id,rtc,sigplan,cycle_time,health,phase_no,phase_time,active_groups,groupscolour,ip "+
"FROM status_data where rtc>='" + fromDate + "' and rtc<'" + toDate + "' and "+
"site_id=" + SiteId + " order by rtc desc limit "+recordLimit+" )as temp ORDER BY RTC ASC";
I wrote the hql version to get data from HealthLog table as
String hql = " select f from (select h from HealthLog h where rtc>='"+fromDate+"' and rtc <'"+toDate+"' "
+ "and siteId = "+siteId+" order by rtc desc limit "+limit+" ) as f order by rtc asc ";
return super.readListByHql(hql);
But the above hql throws the following exception
org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: ( near line 1, column 16 [ select f from (select h from com.traff.hibernate.model.HealthLog as h where rtc>='1974-08-01 14:10:00.0' and rtc <'1974-09-01 23:46:20.6' and siteId = 20 order by rtc desc limit 50000 ) as f order by rtc asc ]
at org.hibernate.hql.internal.ast.QuerySyntaxException.convert(QuerySyntaxException.java:54)
at org.hibernate.hql.internal.ast.QuerySyntaxException.convert(QuerySyntaxException.java:47)
at org.hibernate.hql.internal.ast.ErrorCounter.throwQueryException(ErrorCounter.java:79)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.parse(QueryTranslatorImpl.java:276)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:180)
at org.hibernate.hql.intern
I also tried the below code snippet but that giving me wrong results
Criteria criteria = createEntityCriteria();
criteria.add(Restrictions.ge("rtc", fromDate));
criteria.add(Restrictions.lt("rtc", toDate));
criteria.add(Restrictions.eq("siteId", siteId));
criteria.setMaxResults(limit);
criteria.addOrder(Order.asc("rtc"));
criteria2 = criteria;
criteria2.addOrder(Order.desc("rtc"));
return criteria2.list();
Which is the correct way to achieve the result?

First of all, as already mentioned in the comments, you cannot do a subquery within the FROM clause in HQL.
See: Hibernate Documentation
Secondly, the limit keyword is not supported by HQL.
Usually you would use query.setFirstResult(0) and query.setMaxResults(recordLimit) methods where query has the type of the Query Interface. But since you are using the limit in a subquery, there is no way.
See: How to set a limit to inner query in Hibernate?
Some options:
Use a native SQLQuery
Since you are only sorting in the outer Query. You could only execute the inner query and sort in Java.
Example for Option 2:
Session session = factory.openSession();
Query query = session
.createQuery("FROM HealthLog "
+ "WHERE rtc >= :rtcL and rtc < :rtcG and siteId = :siteId "
+ "ORDER BY rtc DESC");
query.setParameter("rtcL", fromDate);
query.setParameter("rtcG", toDate);
query.setParameter("siteId", siteId);
query.setFirstResult(0);
query.setMaxResults(recordLimit);
List<HealthLog> res = query.list();
session.close();
Collections.sort(res, new Comparator<HealthLog>() {
public int compare(HealthLog o1, HealthLog o2) {
return o1.getRtc().compareTo(o2.getRtc());
}
});
The query above returns HealthLogs with all attributes. If you want to only retrieve specific attributes, you can add a SELECT new HealthLog(siteId,rtc,sigplan,cycle_time,...) to your Query with a fitting constructor in HealthLog.
Please note that the code snippet might not be ready to use, since i do not know your model and attribute names.

Related

How do I write join in Ebean Java ORM language

Currently my code is
int customerId = 4;
String sql = "select id from coupon as A join coupon_use "
+ "as B on A.id=B.coupon where B.customer=" + customerId
+ " and B.like_at is not null;";
RawSql rawSql = RawSqlBuilder.parse(sql).create();
Query<Coupon> query = Ebean.find(Coupon.class);
query.setRawSql(rawSql);
List<Coupon> list = query.findList();
return ok(Json.toJson(list));
How do I avoid writing manual sql query but still have the ORM generate that query and return me the result?
Ebean will add appropriate joins based on the paths/properties used in the where and order by etc.
where couponUse.likeAt is not null.
Assuming couponUse.likeAt is the correct expression path ... Ebean will add a join to support the expression automatically.

How can I get the alias name for my ResultSet from a Subquery?

I have a problem with getting the alias of the columnnames for my ResultSet.
I made a subquery, where i use the alias function(MAX(...) in SQL) but everytime I execute the Statement, I get java.sql.SQLException because the column name is not valid. And I use the current alias where I call the getString - Function of my ResultSet.
This is my SQL-Statement in Eclipse:
String sql = "SELECT a.steelgrade, a.prod_order_id, a.prod_order_item_pos, "
+"a.prod_order_version, a.strip_thickn_aim, a.strip_width_aim, "
+"a.customer, a.order_weight_plan, b.grund_kommlos, b.coil_weight "
+"FROM (SELECT prod_order_id, prod_order_item_pos, "
+ "MAX (prod_order_version) AS max_version "
+ "FROM production_order "
And in the ResultSet while.next()-Loop:
prod_order_version = AuftraegeProduction.getString("max_version");
This is the whole SQL-Statement( in the Database it works fine!):
SELECT a.steelgrade, a.prod_order_id, a.prod_order_item_pos,
a.prod_order_version, a.strip_thickn_aim, a.strip_width_aim,
a.customer, a.order_weight_plan, b.grund_kommlos, b.coil_weight
FROM (SELECT prod_order_id, prod_order_item_pos,
MAX (prod_order_version) AS max_version
FROM production_order
GROUP BY prod_order_id, prod_order_item_pos) c
JOIN
production_order a
ON a.prod_order_id = c.prod_order_id
AND a.prod_order_item_pos = c.prod_order_item_pos
AND a.prod_order_version = c.max_version
JOIN pps_plan_slab b
ON b.prod_order_id = c.prod_order_id
AND b.prod_order_item_pos = c.prod_order_item_pos
AND b.prod_order_version = c.max_version
WHERE a.strip_thickn_aim > 1.78
AND a.strip_thickn_aim < 3.26
AND a.steelgrade = 'M4R51'
AND a.prod_order_id NOT BETWEEN '0999551' AND '0999599'
AND a.strip_width_aim BETWEEN 1126 AND 1166
AND NVL (a.order_weight_plan, 0) > 0
AND a.order_weight_plan >= b.coil_weight
ORDER BY prod_order_id ASC
Anyone have a suggestion?
Maurice
when using aggregate functions max(),min(),sum(),... you must use group by clause clause.

Setting ORDER BY and LIMIT clause on JPA Query

I'm very, very new to Hibernate and JPA. I want to be able to apply ORDER BY and LIMIT clauses to a Hibernate(?) query, but am coming up empty. NOTE: I inherited this code.
Here is the current code:
public SomeCoolResponse getSomeCoolResponse(String myId) {
String queryString = "select aThing from AWholeBunchOfThings aThing " +
"join aThing.thisOtherThing oThing join oThing.StillAnotherThing saThing " +
"where saThing.subthing.id = :id";
Query q = getEntityManager().createQuery(queryString);
q.setParameter("id", myId);
List<MyThings> list = q.getResultList();
if(list.size() > 0) {
return list.get(0);
}
return null;
}
Instead of getting an entire list and then just returning the first result (which is the only one we need), I'd like to be able to apply a LIMIT 0,1 clause so that the query will be faster. Also, the query needs to be sorted descending on aThing.created which is a UNIX timestamp integer.
I've tried altering queryString like this:
String queryString = "select aThing from AWholeBunchOfThings aThing " +
"join aThing.thisOtherThing oThing join oThing.StillAnotherThing saThing " +
"where saThing.subthing.id = :id ORDER BY aThing.created LIMIT 0,1";
But Hibernate still returns the entire set.
I've looked at using the JPA CriteriaBuilder API, but it hurt my brain.
I'm a total n00b when it comes to this, and any help is greatly appreciated!
I think you need
q.setMaxResults(1);
See also the accepted answer here.
How do you do a limit query in HQL?
As to the "order by" clause you may include it in the queryString.
The JPQL equivalent to LIMIT start,max is:
setFirstResult and setMaxResults:
q.setFirstResult(start);
q.setMaxResults(limit);

How to Count the rows in Hibernate Query Language?

I am trying to get just the count of the rows returned rather than all the results from the table.
I saw that this can be done like this:
( (Integer) session.createQuery("select count(*) from ....").iterate().next() ).intValue()
But when trying to store this query in an integer format(it says cannot convert from Query to Integer)
I am using a dynamic query where the values will be mentioned below the query like this
theQuery = "select count(*) from THM as thm " +
"join thm.TMC as tmc " +
"join tmc.TIMCC as timcc " +
"where thm.Qid = :Qid and thm.Cv = :Cv and timcc.Did = :Did and timcc.Cv= :Cv";
Query query = session.createQuery(theQuery);
query.setInteger("Qid", Integer.parseInt(Qid));
query.setInteger("Did", Did);
query.setInteger("Cv",cV);
Now, how can i get a count of all the rows returned by using Hibernate query in a variable without using list.size but directly from the query?
Have you tried the query.uniqueResult(); ? As your Select count(*) will give you only one number, you should be able to retrieve it with this like int count = (Integer)query.uniqueResult();
To count based on a Criteria you can do this:
Criteria criteria = currentSession().createCriteria(type);
criteria.setProjection(Projections.rowCount());
criteria.uniqueResult();
I'm using the Criteria right now so I know for sure that it works. I saw the uniqueResult() solution on a website here: http://www.jroller.com/RickHigh/entry/hibernate_pagination_jsf_datagrid_prototype1
you can do this
long count = (long)session.createQuery("SELECT COUNT(e) FROM Employees e").getSingleResult();
Try it.
Long count = ((Long) session.createQuery("select count(*) from Book").uniqueResult());
Integer totalBooks = count.intValue();
Work for me
int list=(int)
sessionFactory.getCurrentSession().createSQLQuery("select count(*) as count from
Book").addScalar("count",IntegerType.INSTANCE).uniqueResult();

More elegant way to write a hibernate query

Can someone help me write a better code. I tried this but its not working :
Query query = session.createQuery("from MyTable order by :sortvariable :sortorder");
query.setParameter("sortvariable", sortvar);
query.setParameter("sortorder", order);
This is not working as well
Query query = session.createQuery("from MyTable table order by table." + sortvar + " " + " :sortorder");
query.setParameter("sortorder", order);
I managet to get it working with this :
Query query = session.createQuery("from MyTable table order by table." + sortvar + " " + order);
I need to do this with query because I'm using setMaxResults() and setFirstResult().
I don't think you can use parameters to identify keywords that way. Is it possible to do what you're trying to do using the criteria API?
boolean sortAscending = ...;
Criteria criteria = session.createCriteria(MyTable.class);
criteria.addOrder(sortAscending? Order.asc(sortVar): Order.desc(sortVar));

Categories

Resources