从 Derby 获取 PreparedStatement 查询

Posted

技术标签:

【中文标题】从 Derby 获取 PreparedStatement 查询【英文标题】:get PreparedStatement query from Derby 【发布时间】:2016-04-25 13:22:56 【问题描述】:

我正在尝试连接到数据库、运行查询并打印出查询。到目前为止我有什么工作,但我需要得到输出并将它的特定部分分配给String

public static void main(String args[]) 
        BasicConfigurator.configure();
        Logger.getGlobal().setLevel(Level.INFO);
        PreparedStatement preparedStatement = null;
        try 
            connect();
            String sql = "SELECT * FROM foo WHERE ID = ?";
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setInt(1, 1);
            try (ResultSet resultSet = preparedStatement.executeQuery()) 
                while (resultSet.next()) 
                    break;
                
            
            //String usedSql = "query should  go here";
         catch (SQLException ex) 
            Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
         finally 
            if (preparedStatement != null) 
                try 
                    preparedStatement.close();
                 catch (SQLException ex) 
                    Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
                
            
            disconnect();
        
    

我正在使用 log4jdbc 监视我的查询。

目前我得到如下日志输出:

594 [main] DEBUG jdbc.foo  - 1. Connection.new Connection returned   java.sql.DriverManager.getConnection(DriverManager.java:664)
608 [main] DEBUG jdbc.foo  - 1. PreparedStatement.new PreparedStatement returned   com.example.Test.main(Test.java:63)
608 [main] DEBUG jdbc.foo  - 1. Connection.prepareStatement(SELECT * FROM foo WHERE ID = ?) returned net.sf.log4jdbc.PreparedStatementSpy@7d70d1b1  com.example.Test.main(Test.java:63)
608 [main] DEBUG jdbc.foo  - 1. PreparedStatement.setInt(1, 1) returned   com.example.Test.main(Test.java:64)
608 [main] DEBUG jdbc.foo  - 1. PreparedStatement.setMaxRows(1) returned   com.example.Test.main(Test.java:65)
609 [main] DEBUG jdbc.sqlonly  -  com.example.Test.main(Test.java:66)
1. SELECT * FROM foo WHERE ID = 1 

我想将SELECT * FROM foo WHERE ID = 1 分配给usedSql。我该怎么做?

【问题讨论】:

preparedStatement.toString() 给你什么? @Berger: net.sf.log4jdbc.PreparedStatementSpy@7d70d1b1 我想这已经回答了here 不,它没有。不知道为什么该答案被标记为正确,而它所做的只是说不可能,而显然不是,因为我已经完成了上面的大部分工作。 【参考方案1】:

通常preparedStatement.toString() 会给您查询(包括绑定参数)。但这取决于PreparedStatement 的实际实现(例如,使用 PostgreSQL impl 可以)。

您提到preparedStatement.toString() 会为您返回net.sf.log4jdbc.PreparedStatementSpy@7d70d1b1。我不熟悉 log4jdbc,但我看起来像 PreparedStatementSpy 正在包装你的实际 PreparedStatement。要从您的 preparedStatement 获取它,请尝试类似

if(preparedStatement instanceof PreparedStatementSpy)
     usedSql = ((PreparedStatementSpy) preparedStatement).getRealStatement().toString();

编辑:因为您使用的是Derby,所以简单的toString() 是行不通的。解决此问题的一种方法是使用PreparedStatementSpy.dumpedSql(),它将返回与log4jdbc 用于日志记录的相同字符串。不幸的是,它是一个受保护的方法,你必须使用反射:

if (preparedStatement instanceof PreparedStatementSpy) 
    Method m = PreparedStatementSpy.class.getDeclaredMethod("dumpedSql");
    m.setAccessible(true);
    usedSql = (String) m.invoke(preparedStatement);

// omitted exception handling

【讨论】:

PreparedStatement 实现了java.sql.Wrapper,这可能是访问目标语句的另一种方式。 我正在使用嵌入式 derby,因为它是最快的。我不确定 PreparedStatementSpy 是什么,但 log4jdbc 充当数据库和应用程序之间的代理,以提供有关它们之间通信的其他信息。 @Hooli 查看我的更新以获取可以与 Derby 一起使用的示例 谢谢,可惜 Derby 没有提供 toString() 选项或其他选项,我想这将不得不这样做。 听起来您可以向 Derby 社区记录一个增强请求,以获取有关改进 PreparedStatement.toString 的想法

以上是关于从 Derby 获取 PreparedStatement 查询的主要内容,如果未能解决你的问题,请参考以下文章

apache Derby - 在创建新数据库时获取 java.io.FileNotFoundException: derby.log (Access is denied)

如何将数据从 Ms 访问迁移到 Derby 数据库或如何将数据从 My sql 迁移到 Derby 数据库

无法同时从两个进程连接 derby 数据库

无法从 Netbeans 7.4 启动 derby 数据库

如何从 Spark Shell 中删除 derby.log、metastore_db

Derby分页SQL