多次查询数据库的首选方法?

2022-09-04 20:27:35

在 Java 中使用 JDBC 时,查询数据库的普遍接受的方法是获取连接,从该连接创建语句,然后从该语句执行查询。

// load driver
Connection con = DriverManager.getConnection(..);
Statement stmt = con.createStatement();
ResultSet result = stmt.executeQuery("SELECT..");
// ...

但是,我不确定如何处理对同一数据库的第二个查询。

  1. 是否可以在同一对象上安全地执行另一个查询,或者必须从该对象创建另一个语句才能执行另一个查询?StatementConnection

  2. 如果同一个对象可以用于多个查询,那么该类的目的是什么(因为这样方法的存在会更有意义)?StatementStatementConnection.executeQuery()


答案 1

是的,您可以重用该对象,但关闭返回的对象已打开结果集。StatementResultSetexecuteQuery

有关说明,请参阅 javadoc

默认情况下,每个语句对象只能同时打开一个 ResultSet 对象。因此,如果一个 ResultSet 对象的读取与另一个对象的读取交错,则每个对象都必须由不同的 Statement 对象生成。如果存在打开的语句对象,则 Statement 接口中的所有执行方法都会隐式关闭语句的当前 ResultSet 对象。

因此,将发生以下情况:

// load driver
Connection con = DriverManager.getConnection(..);
Statement stmt = con.createStatement();
ResultSet result = stmt.executeQuery("select ..");
// do something with result ... or not
ResultSet result2 = stmt.executeQuery("select ...");
// result is now closed, you cannot read from it anymore
// do something with result2
stmt.close(); // will close the resultset bound to it

例如,您可以在 jTDS 项目中找到 Statement 的开源实现。在 Statement.executeQuery() 方法中,您可以看到对 initialize() 的调用,该调用关闭了所有已打开的结果集

protected void initialize() throws SQLException {
    updateCount = -1;
    resultQueue.clear();
    genKeyResultSet = null;
    tds.clearResponseQueue();
    // FIXME Should old exceptions found now be thrown instead of lost?
    messages.exceptions = null;
    messages.clearWarnings();
    closeAllResultSets();
}

答案 2

以编程方式,可以对多个查询重用同一连接和同一语句,并在末尾关闭该语句和连接。

但是,这不是一个好的做法。应用程序性能对访问数据库的方式非常敏感。理想情况下,每个连接应尽可能短地打开。然后,必须池化连接。按照这个,您可以将每个查询括在一个块中。这也是大多数 SQL 模板的实现方式。如果并发允许,则可以使用线程池同时触发多个此类查询。{open connection, create a prepared statement, run query, close statement, close connection}


推荐