Как я могу использовать оператор присваивания 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);
Я думаю, после = не должно быть пробела, оператор должен быть записан как =: (без пробелов)