Может ли 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.
Ответы
Ответ 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 с этой функцией.