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

时间:2011-10-26 06:56:32

标签: java sql prepared-statement

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

我在网上看到的所有文档都是批量插入/更新/删除。我从未见过用于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数据库的查询。

4 个答案:

答案 0 :(得分:45)

请参阅the Java Tutorial

  

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

     

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

答案 1 :(得分:6)

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

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

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

/**
 * 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的安全性,并避免不必要的数据库命中。

答案 2 :(得分:3)

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

答案 3 :(得分:3)

如其他答案所指出,JDBC批处理更新不适用于SELECT查询,或者至少不打算用于该查询。

但是,由于该问题将DB2称为RDBMS,因此我认为值得在此指出(尽管现在有点晚了...),该特定数据库的官方驱动程序实际上提供了 使用DB2PreparedStatement#executeDB2QueryBatch()使用此功能(有关详细信息,请参见documentation)。我不知道具有此功能的任何其他JDBC驱动程序。