Как я могу использовать оператор присваивания MySQL (:=) в собственном запросе гибернации?

Я использую Hibernate. Я написал собственный запрос, потому что мне нужно использовать оператор sub select.

Запрос выглядит так:

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

Когда я запускаю этот запрос так:

sessionFactory.getCurrentSession()
    .createSQLQuery(query)
    .setParameter("kid", kid)
    .setParameter("nid", nid)
    .uniqueResult();

Это исключение выходит:

org.hibernate.QueryException: Space is not allowed after parameter prefix ':' ....

Это может из-за := оператор. Я нашел некоторую проблему Hibernate по этому поводу. Этот вопрос все еще открыт. Нет ли решения этой проблемы?

6 ответов

Решение

Вы можете реализовать это немного по-другому. Вам нужно заменить оператор: чем-то другим (скажем, '|' char), а в перехватчике заменить символ '|'. с:.

Таким образом, Hibernate не будет пытаться думать: это парам, но будет игнорировать его

Для логики перехватчика вы можете обратиться к руководству гибернации

Это сработало для меня, используя MySQL 5.

помните, что замена: должна быть сделана только для ':=' и других специфических требований MySQL.. не пытайтесь заменить: для заполнителей параметров. (Hibernate не сможет определить параметры тогда)

Обратите внимание, что HHH-2697 теперь исправлен для Hibernate 4.1.3 и протестирован на Hibernate 4.3.8.Final; Вы должны убежать с обратной косой чертой:

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

Еще одно решение для тех из нас, кто не может перейти на Hibernate 4.1.3.
Просто использовать /*'*/:=/*'*/ внутри запроса. Код Hibernate обрабатывает все между ' как строка (игнорирует это). MySQL, с другой стороны, будет игнорировать все, что находится внутри цитаты, и будет оценивать все выражение для оператора присваивания.
Я знаю, что это быстро и грязно, но работа выполняется без хранимых процедур, перехватчиков и т. Д.

В исключении Hibernate при обнаружении mysql:= оператор Станислав дал другой вариант, кроме перехватчика, чтобы решить эту проблему

Я предпочитаю включать Spring JDBC и выполнять запрос, а не бороться с перехватчиками Hibernate.

Если вы держите свои SQL-файлы подальше от кода Java - попробуйте этот фрагмент кода. Много играл, чтобы получить нужное количество экранирующих слэшей:

String sqlPattern = FileUtils.readFile(this.getClass(), /sql/my_query.sql");
sqlPattern = sqlPattern.replaceAll(":=", "\\\\:=");
Query query = entityManager.createNativeQuery(sqlPattern);

Я думаю, после = не должно быть пробела, оператор должен быть записан как =: (без пробелов)

Другие вопросы по тегам