PreparedStatement.addBatch()可用于SELECT查询吗?

问题描述 投票:20回答:3

想象一下,我有100个SELECT查询,它们因一个输入而不同。 PreparedStatement可用于该值。

我在Web上看到的所有文档都是批量插入/更新/删除。我从未见过用于select语句的批处理。

可以这样做吗?如果是这样,请在下面的示例代码中帮助我。

我想这可以使用“IN”子句来完成,但我更喜欢使用批处理的select语句。

示例代码:

public void run(Connection db_conn, List value_list) {
    String sql = "SELECT * FROM DATA_TABLE WHERE ATTR = ?";
    PreparedStatement pstmt = db_conn.prepareStatement(sql);
    for (String value: value_list) {
        pstmt.clearParameters();
        pstmt.setObject(1, value);
        pstmt.addBatch();
    }
    // What do I call here?
    int[] result_array = pstmt.executeBatch()
    while (pstmt.getMoreResults()) {
        ResultSet result_set = pstmt.getResultSet();
        // do work here
    }
}

我想这也可能是依赖于驱动程序的行为。我正在使用他们的JDBC驱动程序编写针对IBM AS / 400 DB2数据库的查询。

java sql prepared-statement
3个回答
45
投票

the Java Tutorial

该列表可能包含更新,插入或删除行的语句;它还可能包含DDL语句,例如CREATE TABLE和DROP TABLE。但是,它不能包含将生成ResultSet对象的语句,例如SELECT语句。换句话说,列表只能包含产生更新计数的语句。

该列表在创建时与Statement对象关联,最初为空。您可以使用方法addBatch将SQL命令添加到此列表中。


6
投票

JDBC不允许创建批处理的SELECT查询,在我看来这是一个令人沮丧的限制,特别是因为预处理语句不允许您指定可变数量的参数,如IN (...)子句。

JavaRanch文章F.J链接建议通过创建一系列固定大小的查询并加入其结果来模拟批处理,这对我来说似乎是一个麻烦且次优的修复;你必须现在手动构建和处理多个查询,并多次点击数据库。如果为手动定义的批次选择的数字很差,那么您最终可能会多次访问数据库以回答简单的查询。

相反,我已经采取动态构建PreparedStatement对象与我需要的字段数。这确实意味着我们可能创建比手动批处理更多的PreparedStatements,但是我们限制了我们访问数据库的频率并简化了我们的实现,我认为这两者都是一个更重要的问题。

/**
 * Use this method to create batch-able queries, e.g:
 * "SELECT * FROM t WHERE x IN (?, ?, ?, ?)"
 * Can be built as:
 * "SELECT * FROM t where x IN ("+getLineOfQs(4)+")"
 */
public static String getLineOfQs(int num) {
  // Joiner and Iterables from the Guava library
  return Joiner.on(", ").join(Iterables.limit(Iterables.cycle("?"), num));
}

/**
 * Gets the set of IDs associated with a given list of words
 */
public Set<Integer> find(Connection conn, List<String> words)
    throws SQLException {
  Set<Integer> result = new HashSet<>();
  try(PreparedStatement ps = conn.prepareStatement(
      "SELECT id FROM my_table WHERE word IN ("+
      getLineOfQs(words.size())+")")) {
    for(int i = 0; i < words.size(); i++) {
      ps.setString(i+1, words.get(i));
    }

    try (ResultSet rs = ps.executeQuery()) {
      while(rs.next()) {
        result.add(rs.getInt("id"));
      }
    }
  }
  return result;
}

这对代码来说不是太痛苦,为您提供使用PreparedStatement的安全性,并避免不必要的数据库命中。


3
投票

AddBatch()用于'delete'/'insert'/'update'语句,而不是'select'语句。


2
投票

正如在其他答案中所指出的,JDBC Batch Updates不适用于SELECT查询,或者至少不适合用于此。

但是由于这个问题提到了DB2作为RDBMS,我认为这里值得指出(虽然现在有点晚了......),这个特定数据库的官方驱动程序确实使用DB2PreparedStatement#executeDB2QueryBatch()提供了这个功能(详见documentation) 。我不知道有任何其他JDBC驱动程序具有此功能。

© www.soinside.com 2019 - 2024. All rights reserved.