Ведение журнала PreparedStatements в Java - PullRequest
14 голосов
/ 20 октября 2008

Единственное, что всегда было проблемой, - регистрировать ошибки SQL (JDBC), когда у вас есть PreparedStatement вместо самого запроса.

Вы всегда получаете сообщения типа:

2008-10-20 09:19:48,114 ERROR LoggingQueueConsumer-52 [Logger.error:168] Error 
executing SQL: [INSERT INTO private_rooms_bans (room_id, name, user_id, msisdn, 
nickname) VALUES (?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE room_id = ?, name = ?, 
user_id = ?, msisdn = ?, nickname = ?]

Конечно, я мог бы написать вспомогательный метод для извлечения значений и синтаксического анализа / замены вопросительных знаков на реальные значения (и, вероятно, пойду по этому пути, если я не получу результат этого вопроса), но я просто хотел чтобы узнать, была ли эта проблема решена ранее кем-то еще и / или есть ли какой-нибудь общий помощник по ведению журнала, который бы сделал это автоматически для меня.

Отредактировано после нескольких ответов:

Библиотеки, представленные на данный момент, подходят для регистрации операторов для отладки, что, без сомнения, полезно. Тем не менее, я ищу способ взять сам PreparedStatement (а не какой-то подкласс) и регистрировать его оператор SQL при возникновении ошибки. Я не хотел бы развертывать производственное приложение с альтернативной реализацией PreparedStatement.

Я думаю, что я ищу служебный класс, а не специализацию PreparedStatement.

Спасибо!

Ответы [ 4 ]

6 голосов
/ 12 августа 2010

Я попробовал log4jdbc , и он сделал всю работу за меня.

ПРИМЕЧАНИЕ БЕЗОПАСНОСТИ: На сегодняшний день в августе 2011 года зарегистрированные результаты подготовленного оператора log4jdbc НЕ БЕЗОПАСНЫ для выполнения. Они могут использоваться для анализа, но НИКОГДА не должны возвращаться обратно в СУБД.

Пример журнала, сгенерированного logjdbc:

2010/08/12 16:30:56 jdbc.sqlonly org.apache.commons.dbcp.DelegatingPreparedStatement.executeUpdate (DelegatingPreparedStatement.java:105) 8. Вставить в A_TABLE (ID_FILE, code1, ID_G, ID_SEQUENCE, REF, NAME, бар, DRINK_ID, СУММА, ОПИСАНИЕ, СТАТУС, code2, REJECT_DESCR, ID_CUST_REJ) ЦЕННОСТИ (2, '123', 1, '2', 'аа', 'страх', NULL, '0123', 4317,95, 'Rccc', '0', NULL, NULL, NULL)

Библиотека очень проста в настройке:


Моя конфигурация с HSQLDB :

jdbc.url=jdbc:log4jdbc:hsqldb:mem:sample

С Oracle :

jdbc.url=jdbc:log4jdbc:oracle:thin:@mybdd:1521:smt
jdbc.driverClass=net.sf.log4jdbc.DriverSpy

logback.xml:

<logger name="jdbc.sqlonly" level="DEBUG"/>

Жаль, что это не было в репозитории Maven, но все еще полезно.
Из того, что я попробовал, если установить

Вы получите только ошибочные операторы, однако я не знаю, влияет ли эта библиотека на производительность.

3 голосов
/ 19 июня 2009

Это очень зависит от базы данных. Например, я понимаю, что некоторые драйверы JDBC (например, sybase, возможно, ms-sql) обрабатывают подготовленные операторы, создавая временную хранимую процедуру на сервере, а затем вызывая эту процедуру с предоставленными аргументами. Таким образом, полный SQL фактически никогда не передается от клиента.

В результате API JDBC не предоставляет информацию, которую вы ищете. Возможно, вам удастся привести ваши операторные объекты к внутренней реализации драйвера, но, возможно, нет - ваш сервер приложений вполне может обернуть операторы в свою собственную реализацию.

Я думаю, что вам, возможно, придется просто прикусить пулю и написать свой собственный класс, который интерполирует аргументы в заполнитель SQL. Это будет неудобно, поскольку вы не можете запросить PreparedStatement о параметрах, которые были установлены, поэтому вам придется запомнить их в вспомогательном объекте, прежде чем передавать их в оператор.

Мне кажется, что одна из служебных библиотек, которые обертывают объекты реализации вашего драйвера, является наиболее практичным способом выполнения того, чего вы пытаетесь достичь, но в любом случае это будет неприятно.

2 голосов
/ 13 августа 2015

Использование P6Spy : Oracle, Mysql, JNDI, JMX, Spring и Maven . Сильно настраиваемый. Простая и низкоуровневая интеграция Можно распечатать Stacktrace . Может печатать только тяжелые вызовы - время основано на трехкратном интервале.

0 голосов
/ 19 июня 2009
  1. Если вы используете MySQL, PreparedStatement.toString () в MySQL Connector содержит связанные параметры . Хотя сторонние пулы соединений могут нарушить это.

  2. Подкласс PreparedStatement для построения строки запроса при добавлении параметров. Нет способа извлечь SQL из PreparedStatement, так как он использует скомпилированную двоичную форму.

LoggedPreparedStatement выглядит многообещающе, хотя я еще не пробовал.

Одним из их преимуществ перед прокси-драйвером, который регистрирует все запросы, является то, что вы можете изменить строку запроса перед ее регистрацией. Например, в среде PCI вы можете захотеть замаскировать номера карт.

...