Как я могу использовать оператор присваивания 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 ':' ....

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


person Sanghyun Lee    schedule 27.02.2012    source источник
comment
Есть ли что-нибудь, что может вам здесь помочь? dev.mysql.com/doc/refman/ 5.0 / ru /   -  person ManuPK    schedule 27.02.2012
comment
@ManuPK Спасибо, но это не помогло. Думаю, у моего вопроса нет решения. Я нашел аналогичный вопрос с моим stackoverflow .com / questions / 2712240 /, но хорошего решения нет.   -  person Sanghyun Lee    schedule 27.02.2012


Ответы (7)


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

таким образом, спящий режим не будет пытаться думать, что: является параметром, но проигнорирует его

Информацию о логике перехватчика вы можете найти в руководстве по гибернации

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

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

person Anantha Sharma    schedule 27.02.2012
comment
НАСКОЛЬКО ГЛУПОЕ ГИБЕРНАТ, А? Я могу представить, как идет кодер. Нет, как вообще могло быть двоеточие в SQL. Без шансов! Сделаем так, чтобы не было механизма побега! - person Pedro; 09.11.2012
comment
Извините, был немного зол на то, что пришлось работать над этим. Вышеупомянутое решение применимо только в том случае, если у вас есть только молоток. Вы также можете использовать \:, чтобы избежать двоеточий, хотя в моем случае он сломал каждый именованный параметр (они просто перестали работать). - person Pedro; 09.11.2012

Обратите внимание, что HHH-2697 теперь исправлен для Hibernate 4.1. 3 Теперь вы можете экранировать обратную косую черту:

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
person Ondra Žižka    schedule 29.07.2012
comment
при использовании Hibernate 4.3.7 достаточно одной обратной косой черты, например Запрос PG 9.3 select f( p_tst \:= 1 ) (где в строках Java может быть два, чтобы их избежать) - person Andreas Covidiot; 28.09.2015
comment
Этот ответ должен быть отмечен как правильный, эффективный и более простой. - person Jignesh M. Khatri; 05.02.2021

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

person Mariusz S.    schedule 28.08.2014

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

person leccionesonline    schedule 04.07.2013

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

person varghese    schedule 21.10.2015

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

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

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

person Rocky    schedule 27.02.2012