Подтвердить что ты не робот

Может ли PreparedStatement.addBatch() использоваться для запросов SELECT?

Представьте, что у меня есть 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
    }
}

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

4b9b3361

Ответ 1

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

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

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

Ответ 2

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

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

Вместо этого я начал динамически строить объекты 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

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

Ответ 4

Как указано в других ответах, пакетные обновления JDBC не работают для запросов SELECT или, по крайней мере, не предназначены для этого.

Поскольку в этом вопросе DB2 упоминается как СУБД, я думаю, что здесь стоит отметить (хотя и с небольшим опозданием...), что официальный драйвер для этой конкретной базы данных действительно предлагает эту функцию с использованием DB2PreparedStatement#executeDB2QueryBatch() (см. документация для деталей). Я не знаю ни одного другого драйвера JDBC с этой функцией.