猿问

如何获取PreparedStatement的SQL?

如何获取PreparedStatement的SQL?

我有一个通用的Java方法,具有以下方法签名:

private static ResultSet runSQLResultSet(String sql, Object... queryParams)

它打开一个连接,PreparedStatement使用sql语句和queryParams变量长度数组中的参数构建一个,运行它,缓存ResultSet(在a中CachedRowSetImpl),关闭连接,并返回缓存的结果集。

我在记录错误的方法中有异常处理。我将sql语句记录为日志的一部分,因为它对调试很有帮助。我的问题是记录String变量会sql使用?而不是实际值记录模板语句。我想记录已执行(或尝试执行)的实际语句。

那么......有没有办法获得将由a运行的实际SQL语句PreparedStatement?(没有自己构建它。如果我找不到访问PreparedStatement'sSQL的方法,我可能最终会自己构建它catch。)


收到一只叮咚
浏览 4052回答 3
3回答

元芳怎么了

使用预准备语句,没有“SQL查询”:您有一个包含占位符的声明它被发送到DB服务器并在那里准备这意味着SQL语句被“分析”,解析,表示它的一些数据结构在内存中准备然后,你已经绑定了变量它们被发送到服务器并执行准备好的声明 - 处理这些数据但是没有重构真正的实际SQL查询 - 既不在Java端,也不在数据库端。因此,没有办法获得准备好的语句的SQL - 因为没有这样的SQL。出于调试目的,解决方案要么:使用占位符和数据列表输出语句的代码或者“手动”“构建”一些SQL查询。

幕布斯6054654

它在JDBC API合同中没有任何定义,但是如果你很幸运,有问题的JDBC驱动程序可以通过调用返回完整的SQL&nbsp;PreparedStatement#toString()。即System.out.println(preparedStatement);至少MySQL 5.x和PostgreSQL 8.x JDBC驱动程序支持它。但是,大多数其他JDBC驱动程序不支持它。如果你有这样的,那么你最好的选择是使用Log4jdbc或P6Spy。或者,您也可以编写一个泛型函数,它接受一个ConnectionSQL字符串和语句值,并PreparedStatement在记录SQL字符串和值后返回一个。开球示例:public&nbsp;static&nbsp;PreparedStatement&nbsp;prepareStatement(Connection&nbsp;connection,&nbsp;String&nbsp;sql,&nbsp;Object...&nbsp;values)&nbsp;throws&nbsp;SQLException&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;PreparedStatement&nbsp;preparedStatement&nbsp;=&nbsp;connection.prepareStatement(sql); &nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;(int&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;<&nbsp;values.length;&nbsp;i++)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;preparedStatement.setObject(i&nbsp;+&nbsp;1,&nbsp;values[i]); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;logger.debug(sql&nbsp;+&nbsp;"&nbsp;"&nbsp;+&nbsp;Arrays.asList(values)); &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;preparedStatement;}并用它作为try&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;connection&nbsp;=&nbsp;database.getConnection(); &nbsp;&nbsp;&nbsp;&nbsp;preparedStatement&nbsp;=&nbsp;prepareStatement(connection,&nbsp;SQL,&nbsp;values); &nbsp;&nbsp;&nbsp;&nbsp;resultSet&nbsp;=&nbsp;preparedStatement.executeQuery(); &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;...另一个替代方法是实现一个自定义PreparedStatement,它包装(修饰)构造中的实际&nbsp;PreparedStatement内容并覆盖所有方法,以便它调用真实&nbsp;的方法PreparedStatement并收集所有setXXX()方法中的值,并且懒惰地构造“实际”SQL字符串,只要其中一个executeXXX()调用这些方法(非常有用,但是大多数IDE为装饰器方法提供了自动生成器,Eclipse确实如此)。最后只需使用它。这也基本上是P6Spy和配件已经在引擎盖下做的事情。

开心每一天1111

我正在使用带有MySQL连接器v.5.1.31的Java 8,JDBC驱动程序。我可以使用此方法获得真正的SQL字符串://&nbsp;1.&nbsp;make&nbsp;connection&nbsp;somehow,&nbsp;it's&nbsp;conn&nbsp;variable//&nbsp;2.&nbsp;make&nbsp;prepered&nbsp;statement&nbsp;templatePreparedStatement&nbsp;stmt&nbsp;=&nbsp;conn.prepareStatement( &nbsp;&nbsp;&nbsp;&nbsp;"INSERT&nbsp;INTO&nbsp;oc_manufacturer"&nbsp;+ &nbsp;&nbsp;&nbsp;&nbsp;"&nbsp;SET"&nbsp;+ &nbsp;&nbsp;&nbsp;&nbsp;"&nbsp;manufacturer_id&nbsp;=&nbsp;?,"&nbsp;+ &nbsp;&nbsp;&nbsp;&nbsp;"&nbsp;name&nbsp;=&nbsp;?,"&nbsp;+ &nbsp;&nbsp;&nbsp;&nbsp;"&nbsp;sort_order=0;");//&nbsp;3.&nbsp;fill&nbsp;templatestmt.setInt(1,&nbsp;23);stmt.setString(2,&nbsp;'Google');//&nbsp;4.&nbsp;print&nbsp;sql&nbsp;stringSystem.out.println(((JDBC4PreparedStatement)stmt).asSql());所以它返回像这样的smth:INSERT&nbsp;INTO&nbsp;oc_manufacturer&nbsp;SET&nbsp;manufacturer_id&nbsp;=&nbsp;23,&nbsp;name&nbsp;=&nbsp;'Google',&nbsp;sort_order=0;
随时随地看视频慕课网APP

相关分类

Java
MySQL
我要回答