3 回答

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

TA贡献1876条经验 获得超7个赞
它在JDBC API合同中没有任何定义,但是如果你很幸运,有问题的JDBC驱动程序可以通过调用返回完整的SQL PreparedStatement#toString()
。即
System.out.println(preparedStatement);
至少MySQL 5.x和PostgreSQL 8.x JDBC驱动程序支持它。但是,大多数其他JDBC驱动程序不支持它。如果你有这样的,那么你最好的选择是使用Log4jdbc或P6Spy。
或者,您也可以编写一个泛型函数,它接受一个Connection
SQL字符串和语句值,并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和配件已经在引擎盖下做的事情。

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;
添加回答
举报