24

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?

Sanghyun Lee
  • 21,644
  • 19
  • 100
  • 126
  • Is there any thing that can help you from here? http://dev.mysql.com/doc/refman/5.0/en/assignment-operators.html#operator_assign-value – ManuPK Feb 27 '12 at 05:11
  • @ManuPK Thanks, but it didn't help. I think there's no solution for my question. I found similar question with mine http://stackoverflow.com/questions/2712240/how-to-use-mysql-variables-with-hibernate but there's no good solution. – Sanghyun Lee Feb 27 '12 at 05:26

7 Answers7

32

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
rogerdpack
  • 62,887
  • 36
  • 269
  • 388
Ondra Žižka
  • 43,948
  • 41
  • 217
  • 277
  • 4
    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) – Andreas Covidiot Sep 28 '15 at 09:06
  • This should be marked as correct answer, its effective and much more easy. – Jignesh M. Khatri Feb 05 '21 at 09:13
  • 1
    Works fine, in spring jpa repository for `@Query( value = "<...>" , nativeQuery = true)` , I had to use double backslash `\\:=` inside quotes to avoid compile time error. – RAM237 Oct 19 '21 at 17:00
19

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.

Mariusz S.
  • 321
  • 2
  • 5
5

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)

Anantha Sharma
  • 9,920
  • 4
  • 33
  • 35
  • 7
    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! – Pedro Nov 08 '12 at 22:18
  • 1
    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.) – Pedro Nov 08 '12 at 22:23
0

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

Adam Lear
  • 38,111
  • 12
  • 81
  • 101
leccionesonline
  • 618
  • 1
  • 8
  • 23
0

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

Community
  • 1
  • 1
varghese
  • 33
  • 4
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);
Zon
  • 18,610
  • 7
  • 91
  • 99
-6

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

Rocky
  • 941
  • 7
  • 11