25

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?

2

7 Answers 7

33

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
Sign up to request clarification or add additional context in comments.

3 Comments

using Hibernate 4.3.7 only one backslash is enough, e.g. PG 9.3 query select f( p_tst \:= 1 ) (where it may be two in Java strings to escape them)
This should be marked as correct answer, its effective and much more easy.
Works fine, in spring jpa repository for @Query( value = "<...>" , nativeQuery = true) , I had to use double backslash \\:= inside quotes to avoid compile time error.
20

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.

Comments

6

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)

2 Comments

HOW STUPID IS HIBERNATE HUH? I can imagine the coder going. Nah, how could there EVER be a colon in the SQL. No chance! Let's make it so there is no escaping mechanism!
Sorry, was a bit pissed of about having to work around. The solution above is only if you only have a hammer. You can also use \: to escape the colons, though in my case, it broke every single named parameter (they just stopped working.)
0

I prefer to include Spring JDBC and execute the query rather than fight against Hibernate interceptors.

Comments

0

in Hibernate exception on encountering mysql := operator Stanislav gave another option other than interceptor to solve this issue

Comments

0

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);

Comments

-6

I guess there should not be a space after = , the operator should be written as =: (without any spaces)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.