• 如何从Oracle, MySql, PostgreSQL的PreparedStatement获得所执行的sql语句?


    一、问题提出

    从且只从一个PreparedStatement中获取执行的sql语句(包括运行时绑定的参数值),是实际工作中经常遇到的一个问题。

    网上很多文章提到用自定义的增强类或中间件(p6spy, log4jdbc)来实现,但这需要对现有代码进行修改,工作量很大,能不能有更直接的办法?

    由于java.sql.PreparedStatement并没有提供相应接口,此功能是否实现及如何实现,不同数据库的JDBC是不一样的。PostgreSQL和MySQL的DBC用toString接口实现了此功能;但对于Oracle,问题比较棘手。

    二、PostgreSQL和MySQL

    PostgreSQL和MySQL可以直接使用toString接口获取sql,且会得到绑定的参数值。两者的区别在于:MySQL会在前面加上类名。

        PreparedStatement ps = con.prepareStatement("SELECT value from sys_param where name=?");
        ps.setString(1, "UNIT_CODE");
        System.out.println(ps.toString());

    PostgreSQL的输出是:SELECT value from sys_param where name='UNIT_CODE',可以直接使用。

    MySQL的输出是:com.mysql.cj.jdbc.ClientPreparedStatement: SELECT value from sys_param where name='UNIT_CODE',此时,只需将“: ”前部分截断即可。

    但Oracle的输出则是:oracle.jdbc.driver.OraclePreparedStatementWrapper@7b98f307,无法使用。

    三、Oracle

    经过仔细分析Oracle JDBC的类,发现oracle.jdbc.internal.OraclePreparedStatement(注意不能是oracle.jdbc.OraclePreparedStatement)提供了一个接口getOriginalSql()。用它进行尝试:

        PreparedStatement ps = con.prepareStatement("SELECT value from sys_param where name=?");
        ps.setString(1, "UNIT_CODE");
        if (ps instanceof OraclePreparedStatement) {
            OraclePreparedStatement ops = (OraclePreparedStatement)ps;
            System.out.println(ops.getOriginalSql());
        }

    输出是:SELECT value from sys_param where name=?,只差绑定的参数值了。

    那么,能不能进一步将绑定参数也解析出来?从目前掌握的信息看,Oracle还做不到。

    四、通用方法

    根据以上,可以构造一个从PreparedStatement获取sql的通用方法,如下:

    public String getSql(PreparedStatement ps) throws SQLException
    {
        if (ps==null || ps.getConnection()==null)
            return null;
    switch (ps.getConnection().getMetaData().getDatabaseProductName().toUpperCase())
        {
        case "ORACLE":
            OraclePreparedStatement ops = (OraclePreparedStatement)ps;
            return ops.getOriginalSql();
        case "MYSQL":
            String temp = ps.toString();
            return temp.substring(temp.indexOf(':') + 1);
        case "POSTGRESQL":
            return ps.toString();
        }
        return ps.toString();
    }
  • 相关阅读:
    怎么查看keras 或者 tensorflow 正在使用的GPU
    tf.layers.Dense与 tf.layers.dense的区别
    pytorch LSTM 简单形式
    JN_0025:在局域网中调试本地loaclhost项目
    JN_0024:浏览器打开弹窗
    JN_0023:谷歌浏览器启动项设置
    H5_0041:定义方法获取URL参数
    H5_0040:iframe 父子页面方法调用
    H5_0039:iframe 页面嵌套格式 安全选项sandbox
    Web_0008:win系统默认80端口被占用的处理方法
  • 原文地址:https://www.cnblogs.com/wggj/p/12762648.html
Copyright © 2020-2023  润新知