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

时间:2012-10-18 20:49:27

标签: java mysql database jdbc

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

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

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

  1. 可以在同一个Statement对象上安全地执行另一个查询,还是必须从Connection对象创建另一个语句才能执行另一个查询?

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

6 个答案:

答案 0 :(得分:7)

是的,您可以重复使用Statement对象,但ResultSet返回的executeQuery对象会关闭已打开的结果集。

有关说明,请参阅javadoc

  

默认情况下,每个Statement对象只能打开一个ResultSet对象   同时。因此,如果读取一个ResultSet对象是   与另一个的读取交错,每个必须已经生成   通过不同的Statement对象。 Statement中的所有执行方法   如果是,接口隐式关闭一个statment的当前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() method中,您可以看到已initialize()已打开的closes all the resultsets来电

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();
}

答案 1 :(得分:3)

以编程方式,您可以为多个查询重用相同的连接和相同的语句,并在最后关闭语句和连接。

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

答案 2 :(得分:2)

如果在线程环境中使用Connection和Statement,我有一件事要添加。 我的经验表明,stmt.executeQuery(..)被保存为在并行环境中使用,但结果是每个查询都被序列化并因此按顺序处理,而不是产生任何加速。 因此,最好为每个线程使用一个新的Connection(而不是Statement)。

对于标准顺序环境,我的经验表明,重用语句完全没有问题,并且不需要手动关闭ResultSet。

答案 3 :(得分:1)

这就是为什么我们在面向对象编程中有类的概念。类定义组成成员,使其实例具有状态和行为。这里语句处理与sql语句相关的所有内容。还有很多功能可以执行,如批处理查询等。

答案 4 :(得分:1)

通常,它是一个查询的一个语句。可能没有必要这样做,但在编写实际应用程序时,您不希望一次又一次地重复这些相同的步骤。这与DRY校长有关,而且随着应用程序的增长,它也将变得更加复杂。

编写处理这种低级(重复)内容的对象是很好的,并提供了通过提供查询来访问db的不同方法。

答案 5 :(得分:1)

我不担心创建新语句。但是,打开数据库连接可能会占用大量资源,而打开和关闭连接会影响性能。

以某种自我管理方式离开联系通常非常糟糕。

您应该考虑使用connection pooling。您通常会发出一个close命令,但是您只是将该连接返回到池中。当您请求新连接时,它将重用您之前提供的连接。

您可能希望为一个连接使用不同的语句。 Statement是一个实现和一个接口。根据您的需要,您有时需要使用CallableStatment。某些逻辑可能会在需要时重复使用。