Can PreparedStatement.addBatch() be used for SELECT queries?

前端 未结 4 813
遇见更好的自我
遇见更好的自我 2020-12-05 14:07

Imagine that I have 100 SELECT queries that differ by one input. A PreparedStatement can be used for the value.

All the documentation I see on the Web is for batch

4条回答
  •  离开以前
    2020-12-05 14:53

    JDBC doesn't allow creating batched SELECT queries, which in my opinion is a frustrating limitation, particularly since prepared statements don't allow you to specify a variable number of arguments, like an IN (...) clause.

    The JavaRanch article F.J links to suggests simulating batching by creating a series of fixed-size queries and joining their results, which seems like a cumbersome and suboptimal fix to me; you have to manually construct and process multiple queries now, and hit the database multiple times. If the numbers chosen for the manually defined batches are poor, you could end up hitting the database quite a few times just to answer a simple query.

    Instead, I've taken to dynamically constructing PreparedStatement objects with the number of fields I need. This does mean potentially we create a larger number of PreparedStatements than we would with the manual batching, but we limit how often we hit the database and simplify our implementation, both of which I view as a more important issues.

    /**
     * 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 find(Connection conn, List words)
        throws SQLException {
      Set 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;
    }
    

    This isn't too painful to code, affords you the safety of using PreparedStatement, and avoids unnecessary database hits.

提交回复
热议问题