Home » Mysql » Execute multiple queries using a single JDBC Statement object

Execute multiple queries using a single JDBC Statement object

Posted by: admin November 29, 2017 Leave a comment

Questions:

Please read before marking this as duplicate. I have searched a lot from google and SO, but I couldn’t the precise answer I am looking for.

My Question: In JDBC, Can I use single Statement object to call executeQuery("") multiple times? Is it safe? OR should I close the statement object after each query, and create new object for executing another query.

E.G:

Connection con;
Statement s;
ResultSet rs;
ResultSet rs2;
try
{
    con = getConnection();
    s = con.prepareStatement();

    try
    {
        rs = s.executeQuery(".......................");

        // process the result set rs
    }
    finally
    {
        close(rs);
    }

    // I know what to do to rs here
    // But I am asking, should I close the Statement s here? Or can I use it again for the next query?

    try
    {
        rs2 = s.executeQuery(".......................");

        // process the result set rs2
    }
    finally
    {
        close(rs2);
    }
}
finally
{
    close(s);
    close(con);
}
Answers:

Yes you can re-use a Statement(specifically a PreparedStatement) and should do so in general with JDBC. It would be inefficient & bad style if you didn’t re-use your statement and immediately created another identical Statement object. As far as closing it, it would be appropriate to close it in a finally block, just as you are in this snippet.

For an example of what you’re asking check out this link: jOOq Docs

Questions:
Answers:

I am not sure why you are asking. The API design and documentation show it is perfectly fine (and even intended) to reuse a Statement object for multiple execute, executeUpdate and executeQuery calls. If it wouldn’t be allowed that would be explicitly documented in the Java doc (and likely the API would be different).

Furthermore the apidoc of Statement says:

All execution methods in the Statement interface implicitly close a statment’s [sic] current ResultSet object if an open one exists.

This is an indication that you can use it multiple times.

TL;DR: Yes, you can call execute on single Statement object multiple times, as long as you realize that any previously opened ResultSet will be closed.

Your example incorrectly uses PreparedStatement, and you cannot (or: should not) be able to call any of the execute... methods accepting a String on a PreparedStatement:

SQLException – if […] the method is called on a PreparedStatement or CallableStatement

But to answer for PreparedStatement as well: the whole purpose of a PreparedStatement is to precompile a statement with parameter placeholders and reuse it for multiple executions with different parameter values.

Questions:
Answers:

I can’t find anything in the API docs that would state, that you shouldn’t call executeQuery() on a given PreparedStatement instance more than once.

However your code does not close the PreparedStatement – a call to executeQuery() would throw a SQLException in that case – but the ResultSet that is returned by executeQuery(). A ResultSet is automatically closed, when you reexecute a PreparedStatement. Depending on your circumstances you should close it, when you don’t need it anymore. I would close it, because i think it’s bad style not to do so.

UPDATE Upps, I missed your comment between the two try blocks. If you close your PreparedStatement at this point, you shouldn’t be able to call executeQuery() again without getting a SQLException.

Questions:
Answers:

A Prepared Statement tells the database to remember your query and to be prepared to accept parameterized variables to execute in that query. It’s a lot like a stored procedure.

Prepared Statement accomplishes two main things:

  1. It automatically escapes your query variables to help guard against SQL Injection.

  2. It tells the database to remember the query and be ready to take variables.

Number 2 is important because it means the database only has to interpret your query once, and then it has the procedure ready to go. So it improves performance.

You should not close a prepared statement and/or the database connection in between execute calls. Doing so is incredibly in-efficient and it will cause more overhead than using a plain old Statement since you instruct the database each time to create a procedure and remember it. Even if the database is configured for “hot spots” and remembers your query anyways even if you close the PreparedStatement, you still incur network overhead as well as small processing time.

In short, keep the Connection and PreparedStatement open until you are done with them.

Edit: To comment on not returning a ResultSet from the execution, this is fine. executeQuery will return the ResultSet for whatever query just executed.

Questions:
Answers:

Firstly I am confused about your code

s = con.prepareStatement();

Is it work well?I can’t find such function in JAVA API,at least one parameter is needed.Maybe you want to invoke this function

s = con.createStatement();

I just ran my code to access DB2 for twice with one single Statement instance without close it between two operation.It’s work well.I think you can try it yourself too.

    String sql = "";
    String sql2 = "";
    String driver = "com.ibm.db2.jcc.DB2Driver";
    String url = "jdbc:db2://ip:port/DBNAME";
    String user = "user";
    String password = "password";
    Class.forName(driver).newInstance();
    Connection conn = DriverManager.getConnection(url, user, password);
    Statement statement = conn.createStatement();
    ResultSet resultSet = statement.executeQuery(sql);
    int count = 0;
    while (resultSet.next()) {
        count++;
    }
    System.out.println("Result row count of query number one is: " + count);
    count = 0;
    resultSet = statement.executeQuery(sql2);
    while (resultSet.next()) {
        count++;
    }
    System.out.println("Result row count of query number two is: " + count);

Leave a Reply

Your email address will not be published. Required fields are marked *