如何使用 Java 中的 Postgres JDBC 驱动程序获取导致 SQLException 的 sql 语句?

Eli*_*jah 5 java postgresql exception-handling exception jdbc

背景

在我当前的项目 - 一个没有 GUI 前端的服务器产品中,我试图编写更好的错误处理支持。错误当前输出到日志中,用户通常不会读取。

我们使用 PostgreSQL 作为我们的数据库后端,并通过数据库池程序使用直接的 JDBC 调用和 DAO 访问它。大多数与数据库相关的异常都包含在一个通用DatabaseException类中,该类实现RuntimeException并尝试从传递的异常中提取调试和状态信息。在我们的特殊情况下,它将访问底层 PostgreSQL 数据库驱动程序 - PSQLException。到目前为止,这种方法在获取关于导致数据库错误的原因的详细信息方面效果很好,下面描述了一个值得注意的例外。

此外,由于我们有非常具体的性能和遗留支持要求,我们有很多自定义 SQL魔法,这使得跟踪堆栈回溯的时间更加密集,但并非不可能或困难。

问题描述

我注意到当我们SQLException因为错误的 SQL 语句而得到 a 时,驱动程序的实现不会返回导致错误的 SQL 语句。在做了一些搜索之后,我发现有一种方法可以在启动时将 PostgreSQL 驱动程序放入调试模式并让它显示有关其内部查询的属性。但是,我们不希望在我们的生产环境中以调试模式运行驱动程序(老实说,我一直无法弄清楚如何让它进入 freakin 模式!)。

有没有其他人之前处理过同样的问题并找到了解决方案?如果没有,是否有一些 OOP 模式可以在执行之前存储查询信息,然后将该信息分配给抛出的异常?还是大多数开发人员只是觉得他们不需要完整的查询来解决数据库问题?老实说,我不需要它,因为我有完整的堆栈跟踪,我可以查找调用查询,但它肯定会加快我的调试速度,因为它是我在错误日志中看到的第一件事。

Bhu*_*ale 5

曾经有 SQLException 时,我曾经在我的客户异常对象中添加 SQL 查询。在我在日志文件中记录异常详细信息的代码中,我也曾经记录 SQL。


ski*_*ppy 1

我假设当您调用执行查询时,您有该语句,并且收到异常,因此此时您同时拥有两者。看来你可以在那里进行分析。

然而,也许你正在进一步了解事情。因此,您可能要做的就是在您自己的 Exception 的自定义子类 DatabaseException 上,添加一个带有 getter 和 setter 的 triggingSQLStatement 成员,然后在您尝试执行该语句的位置,从 PostgreSQL 捕获原始 Exception,创建一个新的 Exception。 DatabaseException,将triggeringSQLStatement设置为您刚刚执行的语句,并在DatabaseException上调用initCause(),将从PostgreSQL捕获的Exception设置为您的异常原因;然后抛出 DatabaseException,捕获它的调用代码将有一个对象,该对象打印出所发生事件的非常不错的堆栈跟踪,并提供对导致问题的 SQL 语句的访问。有关此方法的更多信息,您可能需要研究 Java 异常链。即使您没有使用我刚才描述的所有内容,我认为您也绝对应该已经使用 Java 异常链接。

如果代码中没有任何地方可以访问导致问题的 SQL 语句和引发的异常,我会很好奇为什么以及这是如何可能的。我建议你重新设计你的代码,这样你就有这样的位置。

编辑:由于您希望在日志中首先查看 SQL 语句,因此您可能还可以重写 DatabaseException 的 toString() 方法(或其他适当的方法;我不确定打印出异常时会调用什么)打印出包含的 SQL 语句,假设您按照我上面的描述包含了它。