繁体   English   中英

使用单个 JDBC Statement 对象执行多个查询

[英]Execute multiple queries using a single JDBC Statement object

在 JDBC 中,我可以使用单个Statement对象多次调用executeQuery("")吗? 安全吗? 或者我应该在每次查询后关闭语句对象,并创建新对象来执行另一个查询。

例如:

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

是的,您可以重复使用Statement (特别是PreparedStatement ),并且通常应该使用 JDBC 这样做。 如果您不重用您的语句并立即创建另一个相同的Statement对象,那将是低效和糟糕的风格。 至于关闭它,最好在 finally 块中关闭它,就像您在此代码段中一样。

有关您要问的内容的示例,请查看此链接: jOOq Docs

我不确定你为什么要问。 API 设计和文档表明,将Statement对象重用于多个executeexecuteUpdateexecuteQuery调用是非常好的(甚至有意)。 如果不允许,则会在 Java 文档中明确记录(并且 API 可能会有所不同)。

此外, Statement的 apidoc 说:

如果存在打开的对象,则Statement接口中的所有执行方法都会隐式关闭语句的 [原文如此] 当前ResultSet对象。

这表明您可以多次使用它。

TL;DR:是的,您可以多次对单个Statement对象调用execute ,只要您意识到任何先前打开的ResultSet将被关闭。

您的示例错误地使用PreparedStatement ,并且您不能(或:不应该)能够调用任何接受PreparedStatement上的Stringexecute...方法

SQLException - 如果 [...] 在PreparedStatementCallableStatement该方法

但要答案PreparedStatement还有:一个的整个目的PreparedStatement是预编译与参数占位符的声明,并重新使用它与不同的参数值多次执行。

我在API 文档中找不到任何可以说明您不应在给定PreparedStatement实例上多次调用executeQuery()内容。

但是你的代码不会关闭PreparedStatement -到呼叫executeQuery()将抛出SQLException在这种情况下-但ResultSet是由返回executeQuery() 当您重新执行PreparedStatement时,ResultSet 会自动关闭 根据您的情况,您应该在不再需要它时关闭它。 我会关闭它,因为我认为不这样做是不好的风格。

更新Upps,我错过了您在两个 try 块之间的评论。 如果此时关闭 PreparedStatement,则不应该在没有得到 SQLException 的情况下再次调用 executeQuery()。

Prepared Statement告诉数据库记住您的查询并准备好接受参数化变量以在该查询中执行。 它很像一个存储过程。

Prepared Statement主要完成两件事:

  1. 它会自动转义您的查询变量以帮助防止 SQL 注入。

  2. 它告诉数据库记住查询并准备好接受变量。

数字 2 很重要,因为它意味着数据库只需要解释一次您的查询,然后它就可以准备执行该过程。 所以它提高了性能。

您不应在执行调用之间关闭准备好的语句和/或数据库连接。 这样做效率低得令人难以置信,而且会比使用普通的旧Statement导致更多的开销,因为您每次都指示数据库创建一个过程并记住它。 即使数据库被配置为“热点”并且即使关闭PreparedStatement仍然记住您的查询,您仍然会产生网络开销以及小的处理时间。

简而言之,保持ConnectionPreparedStatement打开,直到您完成它们。

编辑:要评论不从执行中返回ResultSet ,这很好。 executeQuery将为刚刚执行的任何查询返回ResultSet

首先我对你的代码感到困惑

s = con.prepareStatement();

效果好吗

s = con.createStatement();

我只是用一个 Statement 实例运行了两次访问 DB2 的代码,而没有在两次操作之间关闭它。它运行良好。我想你也可以自己尝试一下。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM