Неизвестное количество знаков подстановки (?) в preparedStatement
У меня есть некая форма с checkbox. Например нужно выбрать кол-во комнат в номере отеля. Если 4 чекбокса, то соответственно первый чекбокс - одна комната в номере, второй - две комнаты и т.д. Я хочу получить все подходящие комнаты из базы данных. Для этого использую preparedStatement, код получится что-то типо:
PreparedStatement ps = null;
try (Connection con = dbManager.getConnection()) {
String sql = <<<here my sql>>>
ps = con.prepareStatement(sql);
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
try {
if (ps != null) {
ps.close();
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
Но я заранее не знаю сколько чекбоксов отметит пользователь. Если отметит 2, то надо будет
SELECT * FROM room WHERE number_of_beds = ? or ?;
А если 4, то SELECT * FROM room WHERE number_of_beds = ? or ? or ? or ?;
Как можно вместо ? подставить массив? Или только через циклы и StringBuilder или простую конкатенацию создавать sql?
Ответы (1 шт):
К сожалению в jdbc нет переносимого (т.е. такого, чтоб работал с любой БД) способа передать список значений как одну переменную.
Из доступных опций:
- генерировать запрос с помощью
StringBuilderили чего то подобного. Обратите внимание, что в вопросе у вас ошибка в синтаксисе. Нужно илиnumber_of_beds = ? or number_of_beds = ? or number_of_beds = ?илиnumber_of_beds in (?, ?, ?). - выполнять запрос в цикле для каждого значения параметра. В этом случае нужно использовать
PreparedStament, чтоб быстрей работало, но на каждый запрос все равно будет отдельный вызов по сети. - использовать хранимую процедуру, которая уже на стороне БД сделает этот цикл. Тут мы экономим на вызовах по сети, но привязываемся к конкретной БД.
Для postgres есть вариант с одним параметром. Можно создать массив и его передать:
statement.setArray(1, connection.createArrayOf("integer", numberOfBedsList));
В условии запроса нужно использовать условие number_of_beds = ANY(?).