2

I'm trying to connect to a database, run a query and print out the query. So far what I have works but I need to get the output and assign a particular part of it to a 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();
        }
    }

I'm using log4jdbc to spy on my queries.

At the moment I get logged output like:

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 

I want to assign SELECT * FROM foo WHERE ID = 1 to usedSql. How can I go about doing this?

Hooli
  • 1,135
  • 3
  • 19
  • 46
  • What does `preparedStatement.toString()` give you ? – Arnaud Apr 25 '16 at 13:31
  • @Berger: `net.sf.log4jdbc.PreparedStatementSpy@7d70d1b1` – Hooli Apr 25 '16 at 13:35
  • I think this is already answered [here](http://stackoverflow.com/questions/2382532/how-can-i-get-the-sql-of-a-preparedstatement) – soufrk Apr 25 '16 at 15:04
  • No, it hasn't. No idea why that answer was marked as correct when all it does is say **it's impossible** when clearly it's not since I've done most of it above. – Hooli Apr 25 '16 at 15:13

1 Answers1

1

Usually a preparedStatement.toString() will give you the query (incl. bound parameters). But it depends on the actual implementation of the PreparedStatement (with the PostgreSQL impl this works, for example).

You mentioned that preparedStatement.toString() returns net.sf.log4jdbc.PreparedStatementSpy@7d70d1b1 for you. I'm not familiar with log4jdbc but I looks like PreparedStatementSpy is wrapping your actual PreparedStatement. To get it from your preparedStatement try something like

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

Edit: since you are using Derby a simple toString() won't do. A way around this could be to use PreparedStatementSpy.dumpedSql(), which will return the same string log4jdbc uses for logging. Unfortunately its a protected method and you have to use reflection:

if (preparedStatement instanceof PreparedStatementSpy) {
    Method m = PreparedStatementSpy.class.getDeclaredMethod("dumpedSql");
    m.setAccessible(true);
    usedSql = (String) m.invoke(preparedStatement);
}
// omitted exception handling
nyname00
  • 2,496
  • 2
  • 22
  • 25
  • PreparedStatement implements [java.sql.Wrapper](https://docs.oracle.com/javase/7/docs/api/java/sql/Wrapper.html) which might be another way to gain access to the target statement. – jmehrens Apr 25 '16 at 21:17
  • I'm using derby embedded because it's the fastest. I'm not sure what `PreparedStatementSpy` is but log4jdbc acts as a proxy between the database and your application to provide additional information about the communications between them. – Hooli Apr 26 '16 at 06:54
  • @Hooli see my update for an example that could work with `Derby` – nyname00 Apr 26 '16 at 10:59
  • Thanks, pity that Derby doesn't offer the `toString()` option or some sort of alternative, I guess this will have to do. – Hooli Apr 26 '16 at 11:57
  • Sounds like you could log an enhancement request with the Derby community for your idea about improving PreparedStatement.toString – Bryan Pendleton May 13 '16 at 13:43