Можно ли использовать PreparedStatement.addBatch () для запросов SELECT? - PullRequest
21 голосов
/ 26 октября 2011

Представьте, что у меня есть 100 запросов SELECT, которые отличаются одним входом.PreparedStatement может использоваться для значения.

Вся документация, которую я вижу в Интернете, предназначена для пакетной вставки / обновления / удаления.Я никогда не видел пакетов, используемых для операторов выбора.

Можно ли это сделать?Если это так, пожалуйста, помогите мне, когда приведенный ниже пример кода.

Я полагаю, что это можно сделать с помощью предложения "IN", но я бы предпочел использовать пакетные операторы выбора.

Пример кода:

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
    }
}

Полагаю, это также может зависеть от драйвера.Я пишу запросы к базе данных IBM AS / 400 DB2, используя их драйвер JDBC.

Ответы [ 3 ]

45 голосов
/ 26 октября 2011

См. Учебник по Java :

Этот список может содержать операторы для обновления, вставки или удаления строки; и он также может содержать операторы DDL, такие как CREATE TABLE и DROP TABLE. Однако он не может содержать инструкцию, которая создаст объект ResultSet, например инструкцию SELECT. Другими словами, список может содержать только операторы, которые производят счетчик обновлений.

Список, связанный с объектом Statement при его создании, изначально пуст. Вы можете добавить команды SQL в этот список с помощью метода addBatch.

6 голосов
/ 25 ноября 2013

JDBC не позволяет создавать пакетные SELECT запросы, что, на мой взгляд, является досадным ограничением, особенно потому, что подготовленные операторы не позволяют указывать переменное количество аргументов, например, предложение IN (...).

Ссылка на статью JavaRanch, на которую ссылается FJ, предлагает имитировать пакетирование путем создания серии запросов фиксированного размера и объединения их результатов, что кажется мне громоздким и неоптимальным исправлением;Вы должны вручную создавать и обрабатывать несколько запросов, а также обращаться к базе данных несколько раз.Если числа, выбранные для заданных вручную пакетов, невелики, вы можете в конечном итоге попасть в базу данных несколько раз, просто чтобы ответить на простой запрос.

Вместо этого я принял решение динамически создавать PreparedStatement объекты сколичество полей мне нужно.Это означает, что потенциально мы создаем большее число PreparedStatement с, чем при ручном пакетировании, но мы ограничиваем частоту попадания в базу данных и упрощаем нашу реализацию, обе из которых я считаю более важными.

/**
 * 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 голосов
/ 26 октября 2011

AddBatch () предназначен для операторов «delete» / «insert» / «update», а не для операторов «select».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...