У меня есть общий метод Java со следующей сигнатурой метода:
private static ResultSet runSQLResultSet(String sql, Object... queryParams)
Он открывает соединение, создает с PreparedStatement
помощью оператора sql и параметров в queryParams
массиве переменной длины, запускает его, кэширует ResultSet
(в a CachedRowSetImpl
), закрывает соединение и возвращает кэшированный набор результатов.
У меня есть обработка исключений в методе, который регистрирует ошибки. Я записываю SQL-оператор как часть журнала, так как он очень полезен для отладки. Моя проблема заключается в том, что запись в переменную String sql
записывает оператор шаблона с? Вместо фактических значений. Я хочу записать фактический оператор, который был выполнен (или попытался выполнить).
Итак ... Есть ли способ получить фактический оператор SQL, который будет выполняться PreparedStatement
? ( Не создавая его сам. Если я не смогу найти способ получить доступ к PreparedStatement's
SQL, я, вероятно, в конечном итоге сам создам его в своем catch
.)
источник
Ответы:
Используя подготовленные операторы, «SQL-запрос» отсутствует:
Но реальный реальный запрос SQL не перестраивается - ни на стороне Java, ни на стороне базы данных.
Таким образом, нет никакого способа получить подготовленный оператор SQL - так как нет такого SQL.
В целях отладки решения могут быть следующими:
источник
Это нигде не определено в контракте API JDBC, но, если вам повезет, рассматриваемый драйвер JDBC может вернуть полный SQL, просто вызвав вызов
PreparedStatement#toString()
. Т.е.По крайней мере, драйверы MySQL 5.x и PostgreSQL 8.x JDBC поддерживают его. Однако большинство других драйверов JDBC не поддерживают его. Если у вас есть такой, то лучше всего использовать Log4jdbc или P6Spy .
Кроме того, вы также можете написать универсальную функцию, которая принимает
Connection
строку SQL и значения оператора и возвращаетPreparedStatement
после записи строки SQL и значений. Начальный пример:и использовать его как
Другой альтернативой является реализация пользовательского
PreparedStatement
интерфейса, который оборачивает (украшает) реальноеPreparedStatement
в конструкцию и переопределяет все методы так, что он вызывает методы реальногоPreparedStatement
и собирает значения во всехsetXXX()
методах и лениво создает «фактическую» строку SQL всякий раз, когда один из этиexecuteXXX()
методы называют (вполне рабочей, но большинство IDE обеспечивают автогенераторы методов декоратора, Eclipse делает). Наконец, просто используйте это вместо. Это также в основном то, что P6Spy и супруги уже делают под капотами.источник
logger.debug(sql + " " + Arrays.asList(values))
- я ищу способ войти в оператор SQL с параметрами, уже интегрированными в него. Без зацикливания себя и замены знаков вопроса.PreparedStatement
каждый раз. Не будет ли это не очень эффективным способом, потому что весь смысл вPreparedStatement
том, чтобы создать их один раз и использовать их повсеместно?Я использую Java 8, драйвер JDBC с MySQL коннектором v. 5.1.31.
Я могу получить реальную строку SQL, используя этот метод:
Таким образом, он возвращает что-то вроде этого:
источник
Apache Derby
?Если вы выполнение запроса и ожидали
ResultSet
(вы в этом случае, по крайней мере) , то вы можете просто позвонитьResultSet
«SgetStatement()
выглядеть примерно так:Переменная
executedQuery
будет содержать оператор, который использовался для созданияResultSet
.Теперь я понимаю, что этот вопрос довольно старый, но я надеюсь, что это поможет кому-то ..
источник
Я извлек свой sql из PreparedStatement с помощью prepareStatement.toString (). В моем случае toString () возвращает String так:
Теперь я создал метод (Java 8), который использует регулярные выражения для извлечения запроса и значений и помещает их в карту:
Этот метод возвращает карту, где у нас есть пары ключ-значение:
Теперь - если вы хотите значения в виде списка, вы можете просто использовать:
Если ваш readyStatement.toString () отличается от того, что в моем случае, это просто вопрос «корректировки» регулярного выражения.
источник
Использование PostgreSQL 9.6.x с официальным драйвером Java
42.2.4
:Покажет SQL с
?
уже замененным, что я и искал. Просто добавил этот ответ, чтобы покрыть дело postgres.Я бы никогда не подумал, что это может быть так просто.
источник
Я реализовал следующий код для печати SQL из PrepareStatement
источник
Фрагмент кода для преобразования SQL PreparedStaments со списком аргументов. Меня устраивает
источник
Очень поздно :), но вы можете получить исходный SQL из OraclePreparedStatementWrapper по
источник
oracle.jdbc.driver.OraclePreparedStatementWrapper
не является публичным в oracle.jdbc.driver. Не может быть доступен снаружи пакета. Как вы используете этот класс?Если вы используете MySQL, вы можете регистрировать запросы, используя журнал запросов MySQL . Я не знаю, предоставляют ли другие поставщики эту функцию, но скорее всего, они делают.
источник
Просто функция:
Это хорошо, а также для подготовленного заявления.
источник
.toString()
пара дополнительных строк, чтобы обмануть неопытных пользователей, и на них уже давным-давно ответили.Я использую Oralce 11g и не смог получить окончательный SQL из PreparedStatement. После прочтения @Pascal MARTIN ответа я понимаю почему.
Я просто отказался от идеи использования PreparedStatement и использовал простой форматировщик текста, который соответствовал моим потребностям. Вот мой пример:
Вы выясните, что sqlInParam можно динамически построить в цикле (for, while). Я просто упростил задачу использования класса MessageFormat, который служит в качестве формирователя шаблонов строк для SQL-запроса.
источник
((OraclePreparedStatementWrapper) myPreparedStatement).getOriginalSql()
Для этого вам нужно JDBC-соединение и / или драйвер, который поддерживает ведение журнала sql на низком уровне.
Взгляните на log4jdbc
источник