基于PreparedStatement抓取带参最终SQL(oracle,mysql,PostgreSQL等通用)
在Java中,使用PreparedStatement时,数据库的最终SQL语句是不可见的,因为参数是通过占位符传递的。但是,如果你想要获取实际执行的SQL语句(包括参数值的替换),可以通过调用PreparedStatement的相应方法来实现。
以下是针对Oracle、MySQL和PostgreSQL数据库,获取最终SQL语句的方法:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class FinalSQL {
public static String getFinalSql(PreparedStatement pstmt) throws SQLException {
// 获取数据库元数据
String url = pstmt.getConnection().getMetaData().getURL();
// 根据数据库类型格式化最终SQL
switch (url.split(":")[1]) {
case "//jdbc:oracle":
return getOracleFinalSql(pstmt);
case "//jdbc:mysql":
return getMySQLFinalSql(pstmt);
case "//jdbc:postgresql":
return getPostgreSQLFinalSql(pstmt);
default:
throw new RuntimeException("Database not supported");
}
}
private static String getOracleFinalSql(PreparedStatement pstmt) throws SQLException {
// Oracle JDBC驱动没有提供直接的方法来获取实际执行的SQL,所以通常不可能实现
throw new RuntimeException("Cannot get final SQL for Oracle with JDBC");
}
private static String getMySQLFinalSql(PreparedStatement pstmt) throws SQLException {
// MySQL JDBC驱动提供了一个方法来获取原始SQL语句和参数
String originalSql = pstmt.unwrap(com.mysql.cj.jdbc.StatementImpl.class).getOriginalSql();
// 获取参数并替换占位符
Object[] parameters = pstmt.getParameters();
for (int i = 0; i < parameters.length; i++) {
Object param = parameters[i];
String placeholder = "?";
if (param instanceof byte[]) {
placeholder = "x' " + bytesToHex((byte[]) param) + " '";
} else if (param != null) {
placeholder = "'" + param.toString().replace("'", "''") + "'";
}
originalSql = originalSql.replaceFirst("\\?", Matcher.quoteReplacement(placeholder));
}
return originalSql;
}
private static String getPostgreSQLFinalSql(PreparedStatement pstmt) throws SQLException {
// PostgreSQL JDBC驱动提供了一个方法来获取原始SQL语句和参数
String originalSql = pstmt.unwrap(org.postgresql.jdbc.PgPreparedStatement.class).getSQL();
// 获取参数并替换占位符
Object[] parameters = pstmt.getParameters();
for (int i = 0; i < parameters.length; i++) {
Objec
评论已关闭