Получить SQL-строку из запроса Hibernate

Мне нужно получить строку из запроса Hibernate и обработать ее позже (поэтому я не могу решить ее с помощью "hibernate.show_sql").

Я уже смотрел на Как получить SQL из Hibernate Criteria API (* не * для ведения журнала), но с этим обходным путем я получаю строку запроса SQL, но вместо того, чтобы показывать значение параметра, оно показывает '?'... Есть ли способ получить полную строку SQL со значениями параметров?

Я имею в виду, что с этим решением я получаю "SELECT * FROM USER WHERE NAME=? AND SURNAME=?" но мне нужно получить "SELECT * FROM USER WHERE NAME='John' AND SURNAME='Doe'"...

Идеи?

Ответ 1

Существует инструмент под названием p6spy. Это немного старше, и я боюсь, что он больше не поддерживается. Во всяком случае, это дало мне хорошие результаты.

Изменить: только что обнаружил, что он активно развивается снова. Работает как очарование для меня!

Ответ 2

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

<category name="org.hibernate.type">
      <priority value="TRACE"/>
</category>

Пример вывода:

13:58:51,505 DEBUG [SQL] 
 insert 
        into
            s.audit
            (action, e_s, ip, time, userid, id) 
        values
            (?, ?, ?, ?, ?, ?)
13:58:51,505 TRACE [StringType] binding 'Modify user' to parameter: 1
13:58:51,505 TRACE [StringType] binding 'E' to parameter: 2
13:58:51,505 TRACE [StringType] binding '164.20.81.65' to parameter: 3
13:58:51,505 TRACE [TimestampType] binding '2012-07-30 13:58:51' to parameter: 4
13:58:51,505 TRACE [IntegerType] binding '158' to parameter: 5
13:58:51,505 TRACE [IntegerType] binding '8851' to parameter: 6

И не забывайте, что свойство 'hibernate.show_sql=true', которое вы сказали ранее, чтобы показать также соответствующий SQL.

Ответ 3

Нет такой вещи, как "полная строка SQL со значениями параметров".

Hibernate использует подготовленные операторы, поэтому он отправляет строку запроса с ? и значениями параметров в базу данных отдельно, так что фактический запрос никогда не строится.

Возможно, вы можете найти способ извлечь значения параметров из QueryImpl, но даже в этом случае вы не сможете получить запрос, готовый к выполнению, потому что вам нужно обработать экранирование, преобразование значений параметров в SQL-литералы и т.д.

Ответ 5

Другой вариант - использовать datasource-proxy, который позволяет прослушивать различные события JDBC, включая выполнение запроса.

Вы можете реализовать QueryExecutionListener.beforeQuery, который получает QueryInfo с текстом запроса SQL и всеми параметрами.