从java.sql.PreparedStatement获取查询[重复]

问题

这个问题在这里已有答案:

  • 如何获取PreparedStatement的SQL? 11个答案

在我的代码中,我使用的是java.sql.PreparedStatement

然后我执行setString()方法来填充预准备语句的通配符。

在调用executeQuery()方法并执行查询之前,有没有办法检索(并打印出)最终查询?我只想将其用于调试目的。


#1 热门回答(134 赞)

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

System.out.println(preparedStatement);

根据我的经验,这样做的至少是PostgreSQL 8.x和MySQL 5.x JDBC驱动程序。对于JDBC驱动程序不支持它的情况,最好的办法是使用一个语句包装器,它记录allsetXxx()方法,最后根据记录的信息在toString()上填充一个SQL字符串。例如Log4jdbcorP6Spy


#2 热门回答(25 赞)

在设置绑定值后,可以尝试在预准备语句中调用toString()

PreparedStatement query = connection.prepareStatement(aSQLStatement);
System.out.println("Before : " + query.toString());
query.setString(1, "Hello");
query.setString(2, "World");
System.out.println("After : " + query.toString());

这在你使用JDBC MySQL驱动程序时有效,但我不确定它是否会在其他情况下使用。你可能必须跟踪所有绑定,然后打印出来。

上面代码的示例输出。

Before : com.mysql.jdbc.JDBC4PreparedStatement@fa9cf: SELECT * FROM test WHERE blah1=**NOT SPECIFIED**and blah2=**NOT SPECIFIED**
After : com.mysql.jdbc.JDBC4PreparedStatement@fa9cf: SELECT * FROM test WHERE blah1='Hello' and blah2='World'

#3 热门回答(18 赞)

对于那些寻找Oracle解决方案的人,我从Log4Jdbc的代码中创建了一个方法。你需要提供查询和传递给preparedStatement的参数,因为从中检索它们有点痛苦:

private String generateActualSql(String sqlQuery, Object... parameters) {
    String[] parts = sqlQuery.split("\\?");
    StringBuilder sb = new StringBuilder();

    // This might be wrong if some '?' are used as litteral '?'
    for (int i = 0; i < parts.length; i++) {
        String part = parts[i];
        sb.append(part);
        if (i < parameters.length) {
            sb.append(formatParameter(parameters[i]));
        }
    }

    return sb.toString();
}

private String formatParameter(Object parameter) {
    if (parameter == null) {
        return "NULL";
    } else {
        if (parameter instanceof String) {
            return "'" + ((String) parameter).replace("'", "''") + "'";
        } else if (parameter instanceof Timestamp) {
            return "to_timestamp('" + new SimpleDateFormat("MM/dd/yyyy HH:mm:ss.SSS").
                    format(parameter) + "', 'mm/dd/yyyy hh24:mi:ss.ff3')";
        } else if (parameter instanceof Date) {
            return "to_date('" + new SimpleDateFormat("MM/dd/yyyy HH:mm:ss").
                    format(parameter) + "', 'mm/dd/yyyy hh24:mi:ss')";
        } else if (parameter instanceof Boolean) {
            return ((Boolean) parameter).booleanValue() ? "1" : "0";
        } else {
            return parameter.toString();
        }
    }
}