I am having this error:
10:54:38,330 ERROR SessionFactoryImpl:363 - Error in named query: transactions.auto org.hibernate.hql.ast.QuerySyntaxException: unexpected AST node: : near line 1, column 8 [select :fields from com.TransactionsEntity t where t.transactionDate >= :startDate and t.transactionDate <= :endDate order by id]
unexpected AST node: :
select :fields from com.TransactionsEntity t
Clean named query:
select :fields from com.TransactionsEntity t where t.transactionDate >= :startDate and t.transactionDate <= :endDate order by id
There are any way that I can add using parameteres the columns that I need select? I see that I can't use ":" in the select part of the statement.
Thanks
Query query = session.createQuery("select t.field1, t.field2 from com.TransactionsEntity t where t.transactionDate >= :startDate and t.transactionDate <= :endDate order by id");
It will return you the list of objects.
List<Object[]> returnedList = query.list();
You can iterate it as:
for (Object[] row: returnedList) {
System.out.println("Field 1: " + row[0]);
System.out.println("Field 2: " + row[1]);
}
Related
I have a query which count a given code from 4 tables. I tested this query first in postgresql, it worked as I expected so I tried to translate it to JPQL and I got this error :
java.lang.IllegalArgumentException:
org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected end of
subtree [ select ((select count(*) from *.Record r where
r.codeCampaign =?1 ) + (select count(*) from *.AccountAssociationAction aaa where aaa.codeCampaign = ?1) +
(select count(*) from *.CampaignPayment cp where cp.pk.campaignCode = ?1) + (select count(*) from
*.ActionPeriodDepartment apd
where apd.id.codeCampaign = ?1))]
I can't figure out what is wrong and what does Hibernate mean by "unexpected end of subtree"
The postgresql query :
select (select count(*) from account_association_action aaa where
aaa.code_campaign = 'CAMP01') + (select count(*) from _campaign_payment cp
where cp.campaign_code = 'CAMP01') + (select count(*) from record r where
r.code_campaign ='CAMP01') + (select count(*) from action_period_department apd
where apd.code_campaign = 'CAMP01');
the JPQL query :
#Query(value=" select (select count(*) from Record r where r.codeCampaign =?1 ) + " +
" (select count(*) from AccountAssociationAction aaa where aaa.codeCampaign = ?1) +" +
" (select count(*) from CampaignPayment cp where cp.pk.campaignCode = ?1) +" +
" (select count(*) from ActionPeriodDepartment apd where apd.id.codeCampaign = ?1)")
int countCampaignCodeUses(String campaignCode);
It looks like you need to add nativeQuery=true to #Query annotation otherwise JPA is failing to make sense of a query without from
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.
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.
Clean SQL syntax (MySQL) allows to select with "group by LEFT(...)"
Example:
SELECT * FROM `table` t
WHERE t.field1 = 777 AND t.field2 = 0
GROUP BY LEFT(t.field3, 6)
HAVING COUNT(*) = 4;
But if I try to use HQL:
" select t from TableEntity t " +
" where t.field1 = :field_1 and t.field2 = :field_2 " +
" group by LEFT(t.field3, 6) " +
" having COUNT(*) = :other_condition "
I got an exeption
org.hibernate.hql.ast.QuerySyntaxException: unexpected token: LEFT near line 1, column 12 [
Is it possible to use HQL in this case?
I don't think you can do what you want, because MySQL extends the group by -- an extension not generally supported by other databases. You can do something like this:
SELECT substring(t.field3, 1, 6), count(*) as cnt
FROM `table` t
WHERE t.field1 = 777 AND t.field2 = 0
GROUP BY substring(t.field3, 1, 6)
HAVING COUNT(*) = 4;
Note that the unaggregated columns in the group by are also in the select.
my query is
sql = "SELECT SUM(TOTAL_BYTES_DELIVERED) / SUM(TOTAL_TIME_TAKEN_IN_DELIVERY)
FROM MV_MFT_TRANSFER
WHERE TRANSFER_INITIATION_TIME > :startDate
AND TRANSFER_INITIATION_TIME < :endDate"
Query query = em.createNativeQuery(sql);
query.setParameter("startDate", startDate, TemporalType.DATE);
query.setParameter("endDate", endDate, TemporalType.DATE);
query.getResultList();'
When I run this, I get an error
SQLExceptionTHrown:
<Sep 11, 2012 12:50:46 PM PDT> <Warning> <EclipseLink> <BEA-2005000> <2012-09-11 12:50:46.893--UnitOfWork(1387841584)--Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.4.1.v20120804-d768c4f): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLException: Missing IN or OUT parameter at index:: 1
Error Code: 17041
Call: SELECT SUM(TOTAL_BYTES_DELIVERED) / SUM(TOTAL_TIME_TAKEN_IN_DELIVERY) FROM MV_MFT_TRANSFER WHERE TRANSFER_INITIATION_TIME > :startDate AND TRANSFER_INITIATION_TIME < :endDate
Query: DataReadQuery(sql="SELECT SUM(TOTAL_BYTES_DELIVERED) / SUM(TOTAL_TIME_TAKEN_IN_DELIVERY) FROM MV_MFT_TRANSFER WHERE TRANSFER_INITIATION_TIME > :startDate AND TRANSFER_INITIATION_TIME < :endDate")>
***SQLException in init() TRANSFER METRICS BEAN****
Local Exception Stack:
Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.4.1.v20120804-d768c4f): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLException: Missing IN or OUT parameter at index:: 1
The following solution should work:
sql = "SELECT SUM(TOTAL_BYTES_DELIVERED) / SUM(TOTAL_TIME_TAKEN_IN_DELIVERY)
FROM MV_MFT_TRANSFER
WHERE TRANSFER_INITIATION_TIME > ?
AND TRANSFER_INITIATION_TIME < ?"
Query query = em.createNativeQuery(sql);
query.setParameter(1, startDate, TemporalType.DATE);
query.setParameter(2, endDate, TemporalType.DATE);
query.getResultList();
It seems that if you use positional parameters it will work. You cannot combine named parameters and native query. Here are some links:
http://java.boot.by/scbcd5-guide/ch08s05.html
http://www.wisegeek.com/what-are-native-queries.htm
And many more, just google for: "Only positional parameter binding may be portably used for native queries".
EDIT: More links to questions with similar issues:
How to get all the element from JDBC query
JPA/Hibernate Native Queries do not recognize Parameters
This article was really helpful!
http://software-security.sans.org/developer-how-to/fix-sql-injection-in-java-persistence-api-jpa
The gist of the article is:
These are unsafe queries, don't use it! String concatenation is bad:
List results = entityManager.createQuery("Select order from Orders order where order.id = " + orderId).getResultList();
List results = entityManager.createNativeQuery("Select * from Books where author = " + author).getResultList();
int resultCode = entityManager.createNativeQuery("Delete from Cart where itemId = " + itemId).executeUpdate();
These are safe queries.
/* positional parameter in JPQL */
Query jpqlQuery = entityManager.createQuery("Select order from Orders order where order.id = ?1");
List results = jpqlQuery.setParameter(1, "123-ADB-567-QTWYTFDL").getResultList();
/* named parameter in JPQL */
Query jpqlQuery = entityManager.createQuery("Select emp from Employees emp where emp.incentive > :incentive");
List results = jpqlQuery.setParameter("incentive", new Long(10000)).getResultList();
/* named query in JPQL - Query named "myCart" being "Select c from Cart c where c.itemId = :itemId" */
Query jpqlQuery = entityManager.createNamedQuery("myCart");
List results = jpqlQuery.setParameter("itemId", "item-id-0001").getResultList();
/* Native SQL */
Query sqlQuery = entityManager.createNativeQuery("Select * from Books where author = ?", Book.class);
List results = sqlQuery.setParameter(1, "Charles Dickens").getResultList();
In JPA
when you use this:
Query query = em.createNativeQuery(sql);
you must set index for set parameters. Note that your query have over than one parameter.