Saying position beyond number of declared ordinal parameters - java

I want to perform a native/raw mysql query using hibernate, I have this:
sessionFactory.getCurrentSession().createSQLQuery(
"update table1 set someCounter = someCounter + 1 where id = ?")
.setParameter(1, someId)
.executeUpdate();
I'm getting the error:
threw exception [Request processing failed; nested exception is
org.hibernate.QueryParameterException: Position beyond number of declared ordinal
parameters. Remember that ordinal parameters are 1-based! Position: 2]
with root cause
org.hibernate.QueryParameterException: Position beyond number of declared ordinal
parameters. Remember that ordinal parameters are 1-based! Position: 2
What's wrong here?

Use index as 0 since the parameter index start from 0.
sessionFactory.getCurrentSession()
.createSQLQuery("update table1 set someCounter = someCounter + 1 where id = ?")
.setParameter(0, someId)
.executeUpdate();
Since you are using Hibernate, you can use the named parameter as well i.e.
sessionFactory.getCurrentSession()
.createSQLQuery("update table1 set someCounter = someCounter + 1 where id = :id")
.setParameter("id", someId)
.executeUpdate();

The parameters use a zero based index. Try:
sessionFactory.getCurrentSession().createSQLQuery("update table1 set someCounter = someCounter + 1 where id = ?")
.setParameter(0, someId)
.executeUpdate();
The current Hibernate JavaDocs also specify that setPosition relies on zero based indexing for positional parameters. http://docs.jboss.org/hibernate/orm/4.1/javadocs/org/hibernate/Query.html#setParameter%28int,%20java.lang.Object%29
setParameter
Query setParameter(int position,
Object val)
throws HibernateException
Bind a value to a JDBC-style query parameter. The Hibernate type of the parameter is first detected via the usage/position in the query and if not sufficient secondly guessed from the class of the given object.
Parameters:
position - the position of the parameter in the query string, numbered from 0.
val - the non-null parameter value
Throws:
HibernateException - if no type could be determined
Check the out the parameters section of this document: https://access.redhat.com/knowledge/docs/en-US/JBoss_Enterprise_Web_Server/1.0/html/Hibernate_Core_Reference_Guide/querysql.html#id3043464
There has been some discussion regarding whether the setParameter() method is zero based or one based. This confusion is due to the exception received by the poster noting that parameters are 1 based, while the JavaDoc states that they are zero based. I analyzed the Hibernate source code and believe that they are in fact zero based. Assuming that I checked the right class, the underlying code uses a list to store the parameter bind values, which would imply that the setParameter method is in fact zero based. Checkout the source code for yourself: https://github.com/hibernate/hibernate-orm/blob/master/hibernate-core/src/main/java/org/hibernate/internal/AbstractQueryImpl.java

Positional parameters start from 0 not 1
Native SQL queries support positional as well as named parameters:
update your query by passing 0 instead of 1 in setParameter(1, someId)
sessionFactory.getCurrentSession().createSQLQuery("update table1 set someCounter = someCounter + 1 where id = ?")
.setParameter(0, someId)
.executeUpdate();
resource parameters

To those of you who couldn't resolve based on the solution above, it seems like at times hibernate (depending on the version, I'm using 3) actually gives you the wrong error, for example the issue could be present if you make a syntax error in the hibernate q language:
find("from Student s where s.id = :id")
change it to this:
find("from Student s where s.id = ?")
actually resolved that issue. I guess my main point is that you should also look at your syntax for the issue bc it seems hibernate can incorrectly label this exception.

Related

Query to get record of most recent date

I want to fetch the record from DB on basis of most recent date (latest date).
I have written one query down below which is not working and showing error :
11:55:05 select firstName,lastName from mb_orderhistory where
eventType="PROPOSED_ITEM_EDIT" and orderId=80822 and
MAX(updatedDate) GROUP BY orderId Error Code: 1111. Invalid use of
group function 0.015 sec
This is the query which i have written.
select firstName,lastName from mb_orderhistory where eventType="PROPOSED_ITEM_EDIT" and
orderId=80822 and MAX(updatedDate) GROUP BY orderId;
You can't use an aggregate (aka group) function — like MAX — in a WHERE clause. That's because the WHERE clause is evaluated against every possible row, whereas the aggregate function's value is only defined after you've seen all of the matching rows.
See MySQL's docs on SELECT syntax, and specifically:
In the WHERE expression, you can use any of the functions and operators that MySQL supports, except for aggregate (summary) functions.
Instead, you should just order by the updateDate (in descending order, such that the first row that's outputted is the greatest), and use LIMIT to get only one row:
SELECT ... WHERE orderId=80822 ... ORDER BY updatedDate DESC LIMIT 1
(A GROUP BY on a column doesn't make much sense if you also have an equality predicate on that column (orderId=80822). The predicate means that you will only have one group, and you'll know its value: in this case, 80822. The whole purpose of a GROUP BY is to identify groups; if you already know the group, you don't need it.)
In SQL Server, you can use order by like select top 1 firstname,lastname from <table_name> where <condition> order by updateddate desc
You could try:
select
firstName
,lastName
from mb_orderhistory
where eventType = "PROPOSED_ITEM_EDIT"
and orderId = 80822
and updateDate = (select max(updateDate) from mb_orderhistory where eventType = "PROPOSED_ITEM_EDIT" and orderId = 80822)
Select firstName,lastName
From mb_orderhistory
where eventType="PROPOSED_ITEM_EDIT"
and orderId=80822
and updatedDate = (SELECT MAX(updatedDate) FROM mb_orderhistory)
GROUP BY orderId;
This might be helpful to you! Tx.

Get SQL String substituted with parameters using java

Is there any easy way to get a completed SQL statement after parameter substitution?
I am using elasticsearch-sql to query elastic search with sql statements, however I have to submit the query with all the parameters substituted.
I tried Hibernate Query getQueryString, but the parameter substitution is not happening for those sql strings.
The following sql string is produced:
"SELECT * FROM USER WHERE NAME=? AND SURNAME=?"
rather than:
"SELECT * FROM USER WHERE NAME='Selva' AND SURNAME='Esra'
Appreciate any better idea/thoughts?
1. Named parameters
This is the most common and user friendly way. It use colon followed by a parameter name (:example) to define a named parameter. See examples…
String hql = "SELECT * FROM USER WHERE NAME= :userName AND SURNAME= :surName";
Query query = session.createQuery(hql);
query.setParameter("userName ", "userName");
query.setParameter("surName", "SurName");
List results = query.list();
An object-oriented representation of a Hibernate query. A Query instance is obtained by calling Session.createQuery(). This interface exposes some extra functionality beyond that provided by Session.iterate() and Session.find():
a particular page of the result set may be selected by calling setMaxResults(), setFirstResult()
named query parameters may be used
the results may be returned as an instance of ScrollableResults
Named query parameters are tokens of the form :name in the query string. A value is bound to the integer parameter :foo by calling
setParameter("foo", foo, Hibernate.INTEGER);
for example. A name may appear multiple times in the query string.
JDBC-style ? parameters are also supported. To bind a value to a JDBC-style parameter use a set method that accepts an int positional argument (numbered from zero, contrary to JDBC).
You may not mix and match JDBC-style parameters and named parameters in the same query.
2. Positional parameters
It’s use question mark (?) to define a named parameter, and you have to set your parameter according to the position sequence. See example…
Java
String hql = "from Stock s where s.stockCode = ? and s.stockName = ?";
List result = session.createQuery(hql)
.setString(0, "7277")
.setParameter(1, "DIALOG")
.list();
This approach is not support the setProperties function. In addition, it’s vulnerable to easy breakage because every change of the position of the bind parameters requires a change to the parameter binding code.
Java
String hql = "from Stock s where s.stockName = ? and s.stockCode = ?";
List result = session.createQuery(hql)
.setParameter(0, "DIALOG")
.setString(1, "7277")
.list();
Conclusion
In Hibernate parameter binding, i would recommend always go for “Named parameters“, as it’s more easy to maintain, and the compiled SQL statement can be reuse (if only bind parameters change) to increase the performance.

Hibernate setParemeter 1-based or 0-based? QueryParameterException

Assuming everything else works like a charm (entities, named queries, native named queries) I'm facing weird exceptions while trying to run following query, where date column type is TIMESTAMP:
#NamedNativeQuery(name = "problematicQuery", query = "DELETE FROM mytable WHERE date < ?")
I'm trying to execute this query using following code, where date is java.sql.Timestamp:
Query deleteQuery = em.createNativeQuery("problematicQuery");
deleteQuery.setParameter(1, date);
deleteQuery.executeUpdate();
This code results in following exception:
org.hibernate.QueryParameterException: Position beyond number of declared ordinal parameters. Remember that ordinal parameters are 1-based! Position: 1
When I change the middle code line to this:
Query deleteQuery = em.createNativeQuery("problematicQuery");
deleteQuery.setParameter(0, date);
deleteQuery.executeUpdate();
I'll get the same exception with different position:
org.hibernate.QueryParameterException: Position beyond number of declared ordinal parameters. Remember that ordinal parameters are 1-based! Position: 0
I'm using JBoss 7.2.0.Final (Hibernate version is 4.2.0.CR1), Oracle 11g.
WHAT IS WRONG ? Am I missing something ?
Looks like you use wrong way
em.createNamedQuery("problematicQuery")
rather than
em.createNativeQuery("problematicQuery");
In your case a query created from string "problematicQuery" where no parameters exist
You should use named parameters inside JPA QL: #NamedNativeQuery(name = "problematicQuery", query = "DELETE FROM mytable WHERE date < :dt"
and deleteQuery.setParameter("dt", date);

how to use alias in querydsl?

I am new to querydsl and already in love with it, but I can't get how to use an alias in this query.
QProduct product = QProduct.product;
JPQLQuery jPQLQuery =
from(product)
.where(product.name.locate(searchTerm).as("score").gt(0).or(product.code.locate(searchTerm).as("score").gt(0))).groupBy(product.baseProd);
List<Product> matchedNames = jPQLQuery.orderBy(new NumberPath<Integer>(Integer.class, "score").asc()).offset((pageNumber-1)*10).limit(10).list(product);
my first thought was something like this which throws an error with the generated query as:
java.lang.IllegalArgumentException:
org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token:
as near line 3, column 31 [select product from
mesoft.meshopframework.model.Product product where
locate(?1,product.name) as score > ?2 or locate(?1,product.code) as
score > ?2 group by product.baseProd order by score asc]
could someone show me the coorect way to do this?? I hope it's not necessary for DB to calculate product.name.locate(searchTerm) or the other one again for sorting,
thanks
JPQL has a more restricted syntax compared to SQL, but I don't think your example would work in SQL either.
You can't use aliases in the where part and for order you will need pick one of the locate expressions or order by both of them.

When using Hibernate for Java getting abnormal behavior binding parameterList in HQL

UPDATE
I found the issue. Kind of embarrassing. The client side code was sending a Set of 1 element which was the concatenated String of the report Ids. AArgh!
I am using hibernate v3.6.4 in my Java project. I am getting problems when trying to use a parameter list for a named parameter in my HQL query.
Basically I want to get all the records which match one of the "id"s mentioned in the IN clause.
I tried using both HQL & Criteria I get the same result.
My HQL query,
Set<String> reportIds = new HashSet<String>();
reportIds.add("1");
reportIds.add("2");
String whereClause = "from Report where id IN (:reportIds) ";
Query query = session.createQuery(whereClause);
query.setParameterList("reportIds", reportIds);
Output = empty list. Although I checked by firing manual sql queries in the terminal that there are indeed such records.
I turned on the logging and here is what I see,
Hibernate:
/*
from
Report
where
id IN (
:ids
) */ select
mediavalue0_.id as id31_,
...
from
report mediavalue0_
where
mediavalue0_.id in (
?
)
HibernateLog --> 13:22:36 TRACE org.hibernate.type.descriptor.sql.BasicBinder - binding parameter [1] as [VARCHAR] - 1,2
This is very abnormal because if you notice the final bind statement it considers the toString of the Set! i.e. "1,2" instead of "1" and then "2"!
I was messing around with it so on a whim I decided to directly create the instance of the set inside the setParameterList method call itself. Like so,
query.setParameterList("reportIds", Sets.newHashSet("1","2"));
And it worked! BTW Sets.newHashSet is a construct provided google's guava library. I use the same library to generate the original reportIds set. So there is no inconsistency there.
This query translates to following TRACE,
from
Report
where
id IN (
:ids
) */ select
mediavalue0_.id as id31_,
...
from
report mediavalue0_
where
mediavalue0_.id in (
? , ?
)
HibernateLog --> 13:28:57 TRACE org.hibernate.type.descriptor.sql.BasicBinder - binding parameter [1] as [VARCHAR] - 1
HibernateLog --> 13:28:57 TRACE org.hibernate.type.descriptor.sql.BasicBinder - binding parameter [2] as [VARCHAR] - 2
Notice the separate binds for VARCHAR.
I am totally flummoxed by this odd behavior. Maybe some of you guys can point out what I am doing wrong.
FYI the criteria construct I used (& which resulted in the same output) is like so,
Criteria criteria = session.createCriteria(Report.class);
criteria.add(Restrictions.in("id", reportIds));
P.S. I also used a named sql query with same result
<sql-query name="reportByIds">
<return class="report.Report"/>
SELECT mvr.* from report mvr
WHERE mvr.id IN :ids
</sql-query>
Assume id attribute is of type Long
Set<Long> reportIds = new HashSet<Long>();
reportIds.add(1l);
reportIds.add(2l);
then the query should work, the criteria also works

Categories

Resources