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

kev*_*rpe 22 java sql prepared-statement

想象一下,我有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数据库的查询.

use*_*421 47

请参阅Java教程:

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

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

  • @a_horse_with_no_name我宁愿实际链接到参考资料,没有任何关于教程的权威,其中一些包含了惊人的错误.但是,在我分配给这项任务的45秒内,我找不到合适的问题陈述. (4认同)

dim*_*414 9

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

JavaRanch的文章FJ链接到建议通过创建一系列固定大小的查询并结合其结果来模拟批处理,这对我来说似乎是繁琐且次优的解决方案。您必须立即手动构造和处理多个查询,并多次访问数据库。如果为手动定义的批次选择的数字很差,那么您可能会为了回答一个简单的查询而多次访问数据库。

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

/**
 * 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;
}
Run Code Online (Sandbox Code Playgroud)

这对于代码来说并不太麻烦,为您提供了使用的安全性PreparedStatement,并避免了不必要的数据库访问。

  • 我通常不是番石榴的忠实拥护者,因为虽然从理论上讲它似乎很有用,但我发现它在实践中的用途非常有限。但是,我确实喜欢您在这里使用它的方式。 (2认同)