有一件事总是令人痛苦的是,当你有PreparedStatement而不是查询本身时,记录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 = ?]
当然,我可以编写一个辅助方法来检索值并用真实值解析/替换问号(如果我没有得到这个问题的结果,可能会沿着这条路走下去),但我只是想要要知道此问题是否已由其他人解决,和/或是否有任何通用的日志记录助手可以自动为我做。
在几个答案后编辑:
到目前为止提供的库似乎适合于记录调试语句,这无疑是有用的。但是,我正在寻找一种方法来获取PreparedStatement本身(不是某些子类)并在发生错误时记录其SQL语句。我不想部署具有PreparedStatement备用实现的生产应用程序。
我想我正在寻找一个实用工具类,而不是PreparedStatement专业化。
谢谢!
答案 0 :(得分:6)
我试过了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,描述,状态,CODE2,REJECT_DESCR,ID_CUST_REJ) VALUES (2, '123',1, '2', 'AA', '敬畏',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存储库中,但仍然有用 根据我的尝试,如果你设置
您只会错误地获取语句,但是,我不知道此库是否会对性能产生影响。
答案 1 :(得分:3)
这与数据库有关。例如,我了解一些JDBC驱动程序(例如sybase,可能是ms-sql)通过在服务器上创建临时存储过程来处理预准备语句,然后使用提供的参数调用该过程。因此,完整的SQL实际上永远不会从客户端传递。
因此,JDBC API不会公开您之后的信息。您可以将语句对象转换为内部驱动程序实现,但可能不会 - 您的appserver可能会将语句包装在自己的实现中。
我认为你可能只需要咬紧牙关并编写自己的类,将参数插入到占位符SQL中。这将是尴尬的,因为您不能向PreparedStatement询问已设置的参数,因此在将它们传递给语句之前,您必须在辅助对象中记住它们。
在我看来,包装你的驱动程序实现对象的实用程序库之一是实现你想要实现的最实用的方法,但无论如何都会令人不快。
答案 2 :(得分:2)
使用P6Spy:其Oracle,Mysql,JNDI,JMX, Spring 和 Maven 友好。高度可配置。 简单和低级集成 可以打印堆栈跟踪。 只能打印重度通话 - 基于时间的威胁。
答案 3 :(得分:0)
如果您使用MySQL,MySQL Connector的PreparedStatement.toString()does include the bound parameters。虽然第三方连接池可能会破坏这一点。
子类PreparedStatement,用于在添加参数时构建查询字符串。没有办法从PreparedStatement中提取SQL,因为它使用的是编译的二进制形式。
LoggedPreparedStatement看起来很有希望,但我没有尝试过。
这些记录所有查询的代理驱动程序的一个优点是您可以在记录之前修改查询字符串。例如,在PCI环境中,您可能需要屏蔽卡号。