在 Java 中记录准备语句

2022-09-03 15:10:14

有一件事总是很痛苦,那就是当你有一个ReadyStatement而不是查询本身时,记录SQL(JDBC)错误。

您总是收到如下消息:

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 = ?]

当然,我可以编写一个帮助器方法来检索值并用实际值解析/替换问号(如果我没有得到这个问题的结果,可能会沿着这条路走下去),但我只是想知道这个问题是否被其他人解决了,和/或者是否有任何通用的日志记录帮助程序可以自动为我做到这一点。

经过几个回答后编辑:

到目前为止提供的库似乎适合记录语句以进行调试,这无疑是有用的。但是,我正在寻找一种方法来获取ReadyStatement本身(而不是某些子类),并在发生错误时记录其SQL语句。我不想使用 PreparedStatement 的替代实现来部署生产应用。

我想我正在寻找的是一个实用程序类,而不是PredmentStatement专业化。

谢谢!


答案 1

我尝试了log4jdbc,它为我完成了工作。

安全说明:从今天 2011 年 8 月开始,log4jdbc 预准备语句的记录结果无法安全执行。它们可用于分析,但永远不应反馈到 DBMS 中。

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,BAR,DRINK_ID,AMOUNT,DESCRIPTION,STATUS,CODE2,REJECT_DESCR,ID_CUST_REJ) VALUES (2,'123',1,'2','aa','awe',null,'0123',4317.95,'Rccc','0',null,null,null, null)

该库非常易于设置:


我使用 HSQLDB 的配置:

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

使用甲骨文

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

日志返回.xml :

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

太糟糕了,它不在maven存储库中,但仍然有用。
从我尝试过的,如果你设置

您只会得到错误的语句,但是,我不知道这个库是否对性能有影响。


答案 2

这非常依赖于数据库。例如,我知道一些JDBC驱动程序(例如sybase,也许是ms-sql)通过在服务器上创建一个临时存储过程,然后使用提供的参数调用该过程来处理准备好的语句。因此,完整的SQL实际上从未从客户端传递。

因此,JDBC API 不会公开您所追求的信息。您可能能够将语句对象强制转换为内部驱动程序实现,但可能不会 - 您的应用程序服务器可能会将语句包装在其自己的实现中。

我认为您可能只需要咬紧牙关,编写自己的类,将参数插入占位符SQL中。这将是尴尬的,因为您无法向 PreparedStatement 请求已设置的参数,因此在将它们传递给语句之前,您必须在帮助程序对象中记住它们。

在我看来,包装驱动程序实现对象的实用程序库之一是执行您尝试实现的目标的最实用方法,但无论哪种方式都会令人不快。


推荐