Как получить оператор SQL, который вызвал исключение SQLException с использованием драйвера JDBC Postgres в Java? - PullRequest
4 голосов
/ 21 апреля 2009

Фон

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

Мы используем PostgreSQL в качестве нашей базы данных и обращаемся к нему с помощью прямых вызовов JDBC и DAO через пул базы данных. Большинство исключений, связанных с базой данных, заключены в общий класс DatabaseException, который реализует RuntimeException и пытается извлечь информацию об отладке и состоянии из исключения, которое было передано. В нашем конкретном случае он получит доступ к базовому драйверу базы данных PostgreSQL - PSQLException. Пока что этот подход хорошо работал для получения более подробной информации о том, что вызвало ошибку базы данных, с заметным исключением, описанным ниже.

Более того, поскольку у нас очень специфические требования к производительности и поддержке прежних версий, у нас есть множество пользовательских SQL magic , что делает следующий стек более трудоемким, но не невозможно или сложно.

Описанная проблема

Я заметил, что когда мы получаем SQLException в результате ошибочного оператора SQL, реализация драйвера не возвращает оператор SQL, вызвавший ошибку. Проведя небольшой поиск, я обнаружил, что существует способ перевести драйвер PostgreSQL в режим отладки при запуске и заставить его отображать свойства своего внутреннего запроса. Однако для нас нежелательно запускать драйвер в режиме отладки в нашей производственной среде (и, честно говоря, я не смог выяснить, как перевести его в режим Freakin!).

Вопрос

Кто-нибудь еще имел дело с этой же проблемой раньше и нашел решение? Если нет, существует ли какой-либо шаблон ООП для хранения информации запроса перед выполнением, а затем для присвоения этой информации выданному исключению? Или большинство разработчиков считают, что им не нужен полный запрос для устранения проблем с базой данных? Честно говоря, мне не нужно , потому что у меня есть полная трассировка стека, и я могу посмотреть вызывающий запрос, но это определенно ускоряет мою отладку, так как это первое, что я вижу в ошибке журналы.

Ответы [ 6 ]

4 голосов
/ 21 апреля 2009

Раньше я добавлял SQL-запрос в свой обычный объект Exception, когда есть SQLException. В коде, где я регистрирую подробности исключений в файле журнала, я также записывал SQL-код.

1 голос
/ 21 апреля 2009

Я думаю, что самый простой способ сделать это - использовать сторонний продукт, такой как p6spy. Он попадает между вашим драйвером jdbc и вашей базой данных и сообщает точные запросы, которые выполняются. Его очень легко запустить по требованию, поскольку он реализован как другой драйвер JDBC, который делегирует ваш фактический драйвер JDBC. Очень мощный инструмент, без которого я не могу представить себе работу.

http://www.p6spy.com/

1 голос
/ 21 апреля 2009

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

Однако, может быть, вы догоняете вещи дальше. Итак, вы можете сделать на своем собственном подклассе Exception, DatabaseException, добавить триггерный член SQLStatement с помощью метода get и set, а затем в месте, где вы пытаетесь выполнить инструкцию, перехватить исходное Exception из PostgreSQL, создать новый DatabaseException, задайте для triggeringSQLStatement оператор, который вы только что выполнили, и вызовите initCause () для DatabaseException, чтобы установить исключение, полученное из PostgreSQL, как причину вашего исключения; затем сгенерируйте исключение DatabaseException и вызывающий код, который его перехватит, будет иметь объект, который распечатывает очень приличную трассировку стека того, что произошло, плюс обеспечивает доступ к оператору SQL, вызвавшему проблему. Для получения дополнительной информации об этом подходе вы, возможно, захотите изучить цепочку исключений Java. Даже если вы не используете все то, что я только что описал, я думаю, вам определенно следует использовать цепочку исключений Java.

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

Редактировать: Поскольку вы хотите первым делом увидеть оператор SQL в журнале, вы, вероятно, также можете переопределить метод toString () вашего DatabaseException (или другие соответствующие методы; я не уверен, что вызывается при распечатке исключения) для распечатки включенного оператора SQL, при условии, что вы включили его, как я описал выше.

0 голосов
/ 21 апреля 2009

Еще одно решение для слежки за выполняемыми вами запросами - pgFouine , которое анализирует и создает отчеты по журналам, сгенерированным Postgres

0 голосов
/ 21 апреля 2009

Почему бы не добавить регистратор файлов вокруг всех вызовов JDBC (log4j)?

Всякий раз, когда вы делаете вызов SQL, вы регистрируете SQL и сколько времени потребовалось для его выполнения. Простые вещи.

Мы делаем это для любого вызова внешней системы, например, SOAP-вызовы, RMI, Corba и т. Д. Это оказалось бесценным почти каждый день, и если это влияет на производительность ... Я не заметил!

Если у вас есть проблемы с безопасностью, то есть вы не хотите, чтобы он заходил в файл журнала на клиентском компьютере, вы можете использовать SocketAppender и отправить его на удаленный компьютер для целей централизованного ведения журнала. Это не будет полностью безопасно, но остановит случайного снупера.

0 голосов
/ 21 апреля 2009

Stacktrace может указать вам на метод DAO, который вызвал проблему, не правда ли?

Редактировать после комментария: если ваш SQL-запрос сложен и динамически генерируется из предыдущих частей кода, вы можете записать (уровень TRACE или DEBUG) эти операторы перед их выполнением. В конфигурации регистрации вы можете включить журналы только для DAO.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...