为了账号安全,请及时绑定邮箱和手机立即绑定

如何获取PreparedStatement的SQL?

如何获取PreparedStatement的SQL?

收到一只叮咚 2019-07-26 17:03:33
如何获取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。)
查看完整描述

3 回答

?
元芳怎么了

TA贡献1798条经验 获得超7个赞

使用预准备语句,没有“SQL查询”:

  • 您有一个包含占位符的声明

    • 它被发送到DB服务器

    • 并在那里准备

    • 这意味着SQL语句被“分析”,解析,表示它的一些数据结构在内存中准备

  • 然后,你已经绑定了变量

    • 它们被发送到服务器

    • 并执行准备好的声明 - 处理这些数据

但是没有重构真正的实际SQL查询 - 既不在Java端,也不在数据库端。

因此,没有办法获得准备好的语句的SQL - 因为没有这样的SQL。


出于调试目的,解决方案要么:

  • 使用占位符和数据列表输出语句的代码

  • 或者“手动”“构建”一些SQL查询。


查看完整回答
反对 回复 2019-07-26
?
幕布斯6054654

TA贡献1876条经验 获得超7个赞

它在JDBC API合同中没有任何定义,但是如果你很幸运,有问题的JDBC驱动程序可以通过调用返回完整的SQL PreparedStatement#toString()。即

System.out.println(preparedStatement);

至少MySQL 5.x和PostgreSQL 8.x JDBC驱动程序支持它。但是,大多数其他JDBC驱动程序不支持它。如果你有这样的,那么你最好的选择是使用Log4jdbcP6Spy

或者,您也可以编写一个泛型函数,它接受一个ConnectionSQL字符串和语句值,并PreparedStatement在记录SQL字符串和值后返回一个。开球示例:

public static PreparedStatement prepareStatement(Connection connection, String sql, Object... values) throws SQLException {
    PreparedStatement preparedStatement = connection.prepareStatement(sql);
    for (int i = 0; i < values.length; i++) {
        preparedStatement.setObject(i + 1, values[i]);
    }
    logger.debug(sql + " " + Arrays.asList(values));
    return preparedStatement;}

并用它作为

try {
    connection = database.getConnection();
    preparedStatement = prepareStatement(connection, SQL, values);
    resultSet = preparedStatement.executeQuery();
    // ...

另一个替代方法是实现一个自定义PreparedStatement,它包装(修饰)构造中的实际 PreparedStatement内容并覆盖所有方法,以便它调用真实 的方法PreparedStatement并收集所有setXXX()方法中的值,并且懒惰地构造“实际”SQL字符串,只要其中一个executeXXX()调用这些方法(非常有用,但是大多数IDE为装饰器方法提供了自动生成器,Eclipse确实如此)。最后只需使用它。这也基本上是P6Spy和配件已经在引擎盖下做的事情。


查看完整回答
反对 回复 2019-07-26
?
开心每一天1111

TA贡献1836条经验 获得超13个赞

我正在使用带有MySQL连接器v.5.1.31的Java 8,JDBC驱动程序。

我可以使用此方法获得真正的SQL字符串:

// 1. make connection somehow, it's conn variable// 2. make prepered statement templatePreparedStatement stmt = conn.prepareStatement(
    "INSERT INTO oc_manufacturer" +
    " SET" +
    " manufacturer_id = ?," +
    " name = ?," +
    " sort_order=0;");// 3. fill templatestmt.setInt(1, 23);stmt.setString(2, 'Google');// 4. print sql stringSystem.out.println(((JDBC4PreparedStatement)stmt).asSql());

所以它返回像这样的smth:

INSERT INTO oc_manufacturer SET manufacturer_id = 23, name = 'Google', sort_order=0;


查看完整回答
反对 回复 2019-07-26
  • 3 回答
  • 0 关注
  • 4051 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号