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

2022-09-01 18:09:59

想象一下,我有 100 个 SELECT 查询,它们相差一个输入。“准备语句”可用于该值。

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

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

我想这可以使用“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数据库的查询。


答案 1

请参阅 Java 教程

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

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


答案 2

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

JavaRanch文章F.J链接到建议通过创建一系列固定大小的查询并联接其结果来模拟批处理,这对我来说似乎是一个繁琐且次优的修复;您现在必须手动构建和处理多个查询,并多次命中数据库。如果为手动定义的批次选择的数字很差,则最终可能会多次命中数据库,只是为了回答一个简单的查询。

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

/**
 * 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


推荐