How to use ':' in JPA native query? - java

I am doing some data analysis and I have a SQL query that uses SELECT ..., #rownum:=#rownum+1 as row_number, ... to get the row number along with the results. However when I put this into a native query on my JPA method (using Spring Boot / Spring Data JPA), I get the following exception:
Caused by: java.lang.IllegalArgumentException: org.hibernate.QueryException: Space is not allowed after parameter prefix ':'
I have added #Query(nativeQuery = true, to my method, and have changed my parameters from things like where first_name = :firstname to where first_name = ?1 and removed the #Param annotation from my method parameters, but it hasn't helped.
Is there a way to escape the colon in this query, or some other way of assigning the rownum variable that doesn't use a colon?

To solve this issue you need to escape the two dots with double backslash \\:
"SELECT ..., #rownum\\:=#rownum+1 as row_number, ... "
^^^

Related

SQL error an expression of non-boolean type specified in a context where a condition is expected, near 'AND'

I have the below sql
SELECT * FROM TABLE WHERE COLUMN LIKE CONCAT('%','CMP1','%') OR COLUMN LIKE
CONCAT('%','CMP2','%')
I am replacing this programatically
#Query(value = "SELECT * FROM TABLE WHERE ?1", nativeQuery = true)
List<Items> getAllItems(String param);
I had to append these OR conditions based on the user inputs so the conditions varies hence I used it as a combined OR statements.
How do I resolve this error?
Thanks in advance
Well, let's say I call getAllItems("Hello"). That means you end up trying to run SQL: "SELECT * FROM TABLE WHERE 'Hello'" which is invalid SQL for the exact reason stated: 'Hello' isn't a boolean. You can't put SQLese in that string (you can't call getAllItems("column like CONCAT('%', 'CMP1', '%')") - the point of these queries is that the SQL gets hardcoded and the dynamic data (the string param) is escaped.
You'd have to find a way to write this as a single SQL statement, or, don't use #Query.

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.

jpql left join fetch not returning results for like

In a spring mvc app using hibernate and MySQL, I have written the following query method to return a list of names with patients:
#SuppressWarnings("unchecked")
public Collection<Person> findPersonByLastName(String ln) throws DataAccessException{
Query query = this.em.createQuery("SELECT DISTINCT pers FROM rimPerson pers left join fetch pers.names nm WHERE nm.family LIKE :lnm");
query.setParameter("lnm", ln);
return query.getResultList();
}
This is producing the following hibernate sql:
Hibernate:
select distinct
person0_.hppid as hppid1_340_0_,
names1_.HJID as HJID1_89_1_,
person0_2_.classCode_HJID as classCod2_339_0_,
person0_1_.administrativeGenderCode_HJID as administ2_341_0_,
person0_1_.birthTime_HJID as birthTim3_341_0_,
names1_.DELIMITER_ as DELIMITE2_89_1_,
names1_.FAMILY as FAMILY3_89_1_,
names1_.named_entity_hppid as named5_89_1_,
names1_.SUFFIX as SUFFIX4_89_1_,
names1_.name_entity_HJID as name9_340_0__,
names1_.HJID as HJID1_89_0__
from
rim_person person0_ inner join rim_living_subject person0_1_ on person0_.hppid=person0_1_.hppid
inner join rim_entity person0_2_ on person0_.hppid=person0_2_.hppid
inner join rim_infrastructure_root person0_3_ on person0_.hppid=person0_3_.hppid
left outer join EN names1_ on person0_.hppid=names1_.name_entity_HJID
where names1_.FAMILY like ?
When I call the above jpql method with the following command, it returns zero results:
this.myappService.findPersonByLastName("");
I also get zero results when I cut and past the above generated hibernate code into the MySQL command line client and replace ? with ''.
If, however, I remove the where names1_.FAMILY like ? from the hibernate generated sql above and place the shortened sql into the MySQL command line client, I get four results, eachof which has a value for the lastname field.
How can I change the jpql so that it generates a hibernate query that returns the four results when `` is passed as the empty string parameter? I want the result set to include every result when the user gives empty input, but to give filtered results when the user types in any given text input.
The typical reason that like fails to do what you think it ought to do is to forget to put a wildcard in the pattern string. For example, if you want to match all user names that begin with 'Code' you must do something like name like 'Code%', NOT name like 'Code'. You can control exactly what your predicate matches with careful placement of %s in your string.
Try this to see all entities no matter what the value in family:
this.myappService.findPersonByLastName("%");
It is kinda cheesy to have the caller of findPersionByLastName have to put in the % wildcard. A better implementation is to have the caller specify which last name they are looking for, and then have the code that constructs the query put the wildcard in the right place. When you are looking for last names, you might do something like this:
query.setParameter("lnm", "%" + ln);
That would match anything that ends with the parameter that is passed to the method.

what is the equelent of sql query in hibernate

In SQL Server i am using this query
select *
from Unit c
ORDER BY CONVERT(INT, LEFT(name, PATINDEX('%[^0-9]%', name + 'z')-1)) desc;
I want this query to use in Hibernate. when I use this in Hibernate I got error
java.lang.IllegalArgumentException: org.hibernate.hql.ast.QuerySyntaxException:unexpected token: LEFT near line 1, column 122
[SELECT c FROM models.entities.UnitEntity c WHERE c.expSetId = :expSetId AND isWaitArea=:isWaitArea ORDER BY CONVERT(INT, LEFT(name, PATINDEX('%[^0-9]%', name + 'z')-1)) asc]
some of that is not in the hibernate dialect, you can change left with substring, convert with cast. and as for patindex i couldn't find the substitution. you either can add pathindex to the constructor of the dialect that you use
registerFunction( "patindex", new StandardSQLFunction("patindex") );
or create patindex() to a stored procedure.
then you can use something like this:
from Unit c order by cast(substring(name, 0, PATINDEX('%[^0-9]%', name + 'z')-1) as integer);
or you can use locate() instead of patindex(), but i think it doesn't support regular expression.
I am pretty sure that you can use SQL query with hibernate as well. When you create your hibernate session, you can use something like
session.createSQLQuery("Your Query Here")
Hope this helps.

select column name from H2 with columns that have spaces

I am attempting to query from a tab delimited file with H2 and java. When I select * there are no problems, however, one of the columns has a space in the column name. When I try to query on just that column I get an exception:
Caused by: org.h2.jdbc.JdbcSQLException: Column "EXAMPLE" not found; SQL statement:
It appears as though it is not grabbing both words in the column name (Example ColumnName), but only grabbing the first.
This is what I have:
System.out.println( simpleJdbcTemplate.queryForList( "SELECT Example ColumnName FROM CSVREAD('" + fileName
+ "', null,'UTF-8', chr(9)) where send = 1;", new Object[] {} ) );
I'm guessing there is a special syntax to do this, but I can't seem to find it. I've tried enclosing the column name in: square brackets, single quotes, double quotes, tick marks all to no avail.
Is there a way to query H2 using columns that have spaces in the name?
According to the documentation, double quotes should do the trick.
Remember to escape them correctly in Java, i.e. to just store your column name in a String, use
String exampleColumnName = "\"Example ColumnName\"";
Also, note it is case sensitive, from the documentation:
Quoted names are case sensitive
You can also use brackets [] if you set "MODE=MSSQLServer" in your connection properties. Example:
SELECT * FROM [My Table]
The connection string would look something like this:
jdbc:h2:~/test;MODE=MSSQLServer

Categories