Вопрос-ответ

PreparedStatement with list of parameters in a IN clause [duplicate]

PreparedStatement со списком параметров в предложении IN

Как установить значение для предложения in в PreparedStatement в JDBC при выполнении запроса.

Пример:

connection.prepareStatement("Select * from test where field in (?)");

Если это предложение in может содержать несколько значений, как я могу это сделать. Иногда я заранее знаю список параметров, а иногда и нет. Как справиться с этим случаем?

Переведено автоматически
Ответ 1

Что я делаю, так это добавляю "?" для каждого возможного значения.

var stmt = String.format("select * from test where field in (%s)",
values.stream()
.map(v -> "?")
.collect(Collectors.joining(", ")));

Альтернативное использование StringBuilder (который был первоначальным ответом более 10 лет назад)

List values = ... 
StringBuilder builder = new StringBuilder();

for( int i = 0 ; i < values.size(); i++ ) {
builder.append("?,");
}

String placeHolders = builder.deleteCharAt( builder.length() -1 ).toString();
String stmt = "select * from test where field in ("+ placeHolders + ")";
PreparedStatement pstmt = ...

А затем с радостью устанавливаем параметры

int index = 1;
for( Object o : values ) {
pstmt.setObject( index++, o ); // or whatever it applies
}
Ответ 2

Вы могли бы использовать setArray метод, упомянутый в javadoc ниже:

http://docs.oracle.com/javase/6/docs/api/java/sql/PreparedStatement.html#setArray(int, java.sql.Array)

Код:

PreparedStatement statement = connection.prepareStatement("Select * from test where field in (?)");
Array array = statement.getConnection().createArrayOf("VARCHAR", new Object[]{"A1", "B2","C3"});
statement.setArray(1, array);
ResultSet rs = statement.executeQuery();
Ответ 3

Вы не можете заменить ? в своем запросе произвольное количество значений. Каждое ? является заполнителем только для одного значения. Для поддержки произвольного количества значений вам придется динамически создавать строку, содержащую ?, ?, ?, ... , ? с количеством вопросительных знаков таким же, как количество значений, которые вы хотите получить в своем in предложении.

Ответ 4

Вы не хотите использовать PreparedStatment с динамическими запросами, используя предложение IN, по крайней мере, вы уверены, что у вас всегда меньше переменной 5 или небольшого значения вроде этого, но даже так я думаю, что это плохая идея (не ужасная, но плохая). Поскольку количество элементов велико, будет хуже (и ужаснее ).

Представьте сотни или тысячи возможностей в вашем предложении IN :


  1. Это контрпродуктивно, вы теряете производительность и память, потому что вы кэшируете каждый раз при новом запросе, а PreparedStatement предназначены не только для SQL-инъекции, речь идет о производительности. В этом случае лучше использовать Statement .



  2. У вашего пула есть ограничение на PreparedStatment ( -1 по умолчанию, но вы должны его ограничить), и вы достигнете этого предела ! и если у вас нет лимита или очень большой лимит, у вас есть некоторый риск утечки памяти и, в крайнем случае, ошибок OutOfMemory. Итак, если это для вашего небольшого персонального проекта, которым пользуются 3 пользователя, это не драматично, но вы не хотите этого, если вы работаете в большой компании и вашим приложением пользуются тысячи людей и запрашивают миллионы.



Немного чтения. IBM : соображения по использованию памяти при использовании кэширования подготовленных инструкций

java jdbc