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.
Related
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.
I have this query:
Field<String> yearMonth = DSL.field("FORMATDATETIME({0}, 'yyyy-MM')",
String.class, LICENZE.CREATION_DATE).as("anno_mese");
List<Record3<Integer, String, String>> records =
create.select(DSL.count().as("num_licenze"), LICENZE.EDIZIONE, yearMonth).
from(LICENZE).
groupBy(LICENZE.EDIZIONE, yearMonth).
orderBy(yearMonth).
fetch();
this query generates:
select
count(*) "num_licenze",
"PUBLIC"."LICENZE"."EDIZIONE",
FORMATDATETIME("PUBLIC"."LICENZE"."CREATION_DATE", 'yyyy-MM') "anno_mese"
from "PUBLIC"."LICENZE"
group by
"PUBLIC"."LICENZE"."EDIZIONE",
"anno_mese"
order by "anno_mese" asc
executing it i get: Column "anno_mese" not found; SQL statement
Testing the generated query and removing the quotes from anno_mese in every parts of the query make the query works instead.
Is my query wrong or am I using jooq in the wrong way?
The alias in this query is not so important, I can run the query without using it too but just to understand how it works.
I am using h2 as database.
Thanks for the help
I suspect this is a bug in H2, which I've reported here, because the query looks fine to me. Here are some workarounds that you can do from the jOOQ side:
Don't reference the "anno_mese" column by name
While SQL is a bit repetitive otherwise, you won't notice the difference with jOOQ. I simply moved the as("anno_mese") method call into the SELECT clause. You don't really need it in the GROUP BY and ORDER BY clauses.
Field<String> yearMonth = DSL.field("FORMATDATETIME({0}, 'yyyy-MM')",
String.class, LICENZE.CREATION_DATE);
List<Record3<Integer, String, String>> records =
create.select(DSL.count().as("num_licenze"),
LICENZE.EDIZIONE,
yearMonth.as("anno_mese")).
from(LICENZE).
groupBy(LICENZE.EDIZIONE, yearMonth).
orderBy(yearMonth).
fetch();
Disable quoting in jOOQ generated queries
You can use jOOQ's Settings to prevent schema / table / column names from being quoted. Example:
DSLContext create = DSL.using(connection, SQLDialect.H2,
new Settings().withRenderNameStyle(RenderNameStyle.AS_IS);
Use upper case column names
This will probably work: DSL.field(...).as("ANNO_MESE")
I'm using CriteriaBuilder.concat to concatenate 2 Strings, using code below:
Expression<String> concat = criteriaBuilder.concat(expr1, expr2)
But the generated SQL is something like:
select distinct col_1 || col_2
which causes org.hibernate.hql.ast.QuerySyntaxException:
expecting CLOSE, found '||' near line 1, column 48 [
select count(distinct generatedAlias0.hostname || generatedAlias0.device) from ...
^(1,48)
I wonder how to force it to generate the following SQL which uses the concat() function, instead of the || operator?
select distinct concat(col_1, col_2)
Update:
From the error we can see that the problem is more on the Hibernate (v3.6.10.Final) side, which is why making MySQL to accept || for concatenation doesn't help, also updating to a newer version is not an option for me.
Thank you
I've actually found a workaround. by using #Formula (from Hibernate) instead of CriteriaBuilder for the same task, like this:
#Entity
public class MyEntity {
#Column(name="col_a")
private String colA;
#Column(name="col_b")
private String colB;
#Formula("concat(col_a, col_b)")
private String concated;
//...
}
This way I can use the concated field for CriteriaBuilder.countDistinct:
//...
Expression<?> exp = criteriaBuilder.countDistinct(entity.get("concated"));
criteriaQuery.select(exp);
TypedQuery<Long> query = entityManager.createQuery(criteriaQuery);
return query.getSingleResult();
I wish JPA would (or hopefully already) support countDistinct with multiple columns, then all these mess could have been avoided (see: How to countDistinct on multiple columns, the answer was NO).
I had a similar problem with the concat function.
I have used the concat function in a selectCase and this also returns the same QuerySyntaxException.
My workaround is to use the concat function via criteria builder function:
cb().selectCase().when(cb().equal(root.get(Person_.flag), cb().literal("1")),
cb().function("CONCAT", String.class, root.get(Person_.something), cb().literal(" bla bla bla")))
.otherwise(root.get(Person_.something)))
Hibernate Version 4.3.11.Final
I had this issue as well. The JPA/HQL generated sql query use pipes as concat (which is ||).
I am using Mariadb 10, Springboot-data-jpa2.0.6 (with Hibernate 5.2.17)
Issue example
Given HQL: select x from Xxx x where concat(x.field1, x.field2) = $1
Generated SQL: select ..... where (x.field1 || x.field2) = ?
Reason:
Use of || is deprecated, since mysql 8.0, unless the PIPES_AS_CONCAT SQL mode is enabled: https://dev.mysql.com/doc/refman/8.0/en/mysql-nutshell.html
For mariadb: https://mariadb.com/kb/en/or/
Work around:
(preferred) ranther then use concat function, there is a similar one concat_ws: https://mariadb.com/kb/en/concat_ws/
Use JPA native query #Query(nativeQuery = true, value ="select * from ....")
set global sql_mode=<list of modes which contains PIPES_AS_CONCAT>
(I didn't try this)
I'm using Hibernate for database access. I'm using the following query in my code to fetch the data I need:
SELECT proasset
FROM com.company.claims.participant.AbstractBeneficiary bene
JOIN bene.approvals approval
JOIN bene.proassetkey proasset
join proasset.relatedparties proassetparties
WHERE approval.user_dt > :currentDate
AND approval.user_type = :userType
I'm using it as query in the following:
Query q = this.getSessionFactory().getCurrentSession().createSQLQuery(query.toString())
q.setDate("currentDate", new Date());
q.setString("userType", APPROVER_USER_TYPE);
List<ProAsset> proassets = q.list();
However, I encounter the following when trying to run it:
SQL Error: 933, SQLState: 42000
ORA-00933: SQL command not properly ended
If it matters, the query is being constructed using a StringBuilder and it uses \n to break the lines
Any thoughts on the problem?
It looks like you are trying to mix ORM with a native (plain old SQL) query.
createSQLQuery requires native SQL. You are using classes instead of table names. Try a read of this:
http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/querysql.html
In short you need to write a query like:
select fu
from bar
where situation = 'snafu'
Perhaps you are really wanting to write a namedQuery? They use ORM syntax where you join entities as it seems you are doing in your example.
Check these examples out:
http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/querysql.html#querysql-namedqueries
Correct the syntax by removing the inappropriate clauses. It may be possible to duplicate the removed clause with another SQL statement. For example, to order the rows of a view, do so when querying the view and not when creating it. This error can also occur in SQL*Forms applications if a continuation line is indented. Check for indented lines and delete these spaces.
Alright, so I used createSQLQuery() instead of createQuery() and I was using the column names instead of the variable names.
Here's what my code looks like now:
StringBuilder query = new StringBuilder();
query.append("SELECT proasset\n" +
"FROM com.avivausa.claims.participant.AbstractBeneficiary bene\n" +
"JOIN bene.approvals approval\n" +
"JOIN bene.proAsset proasset\n" +
"join proasset.additionalParties proassetparties\n" +
"WHERE approval.userDate < current_date()\n");
query.append("AND approval.userType = ").append(UserAuditType.APPROVER);
Query q = this.getSessionFactory().getCurrentSession().createQuery(query.toString());
List<ProAsset> proassets = q.list();
Obviously I made some refactoring changes too, but the main changes were what I stated above. Thank you for your responses though!
I'm using Hibernate. I wrote some native query because I need to use sub select statement.
Query looks like this:
SELECT sub.rownum FROM
(SELECT k.`news_master_id` AS id, #row := #row + 1 AS rownum
FROM keyword_news_list k
JOIN (SELECT #row := 0) r
WHERE k.`keyword_news_id` = :kid
ORDER BY k.`news_master_id` ASC) AS sub
WHERE sub.id = :nid
When I run this query like this:
sessionFactory.getCurrentSession()
.createSQLQuery(query)
.setParameter("kid", kid)
.setParameter("nid", nid)
.uniqueResult();
This exception comes out:
org.hibernate.QueryException: Space is not allowed after parameter prefix ':' ....
This might because of := operator. I found some Hibernate issue about this. This issue is still open. Isn't there any solution for this problem?
Note that HHH-2697 is now fixed for Hibernate 4.1.3 You can now escape with backslash:
SELECT k.`news_master_id` AS id, #row \:= #row + 1 AS rownum
FROM keyword_news_list k
JOIN (SELECT #row \:= 0) r
WHERE k.`keyword_news_id` = :kid
ORDER BY k.`news_master_id` ASC
Another solution for those of us who can't make the jump to Hibernate 4.1.3.
Simply use /*'*/:=/*'*/ inside the query. Hibernate code treats everything between ' as a string (ignores it). MySQL on the other hand will ignore everything inside a blockquote and will evaluate the whole expression to an assignement operator.
I know it's quick and dirty, but it get's the job done without stored procedures, interceptors etc.
you can implement this is a slightly different way.. you need to replace the : operator with something else (say '|' char ) and in your interceptor replace the '|' with the : .
this way hibernate will not try to think the : is a param but will ignore it
For the interceptor logic you can refer to the hibernate manual
This has worked for me using MySQL 5.
remember, this replacing of : must be only done to ':=' and other MySQL specific requirments.. don't try to replace the : for the param-placeholders. (hibernate will not be able to identify the params then)
I prefer to include Spring JDBC and execute the query rather than fight against Hibernate interceptors.
in Hibernate exception on encountering mysql := operator Stanislav gave another option other than interceptor to solve this issue
If you keep your SQL-files away from Java code - try this piece of code. Played a lot to get the right number of escaping slashes:
String sqlPattern = FileUtils.readFile(this.getClass(), /sql/my_query.sql");
sqlPattern = sqlPattern.replaceAll(":=", "\\\\:=");
Query query = entityManager.createNativeQuery(sqlPattern);
I guess there should not be a space after = , the operator should be written as =: (without any spaces)