Как присоединиться к элементам списка с помощью", "используя потоки с" в качестве префикса и суффикса тоже
у меня есть инструкция insert, как показано ниже
private final COLUMNS = "NAME,TYPE,STATUS,CATEGORY";
String values = list
.stream()
.collect(Collectors.joining(","));
String insertStatement = String.format("INSERT INTO ifc.documents (%s) VALUES (%s) ",COLUMNS,values);
Я могу легко помещать столбцы без кавычек, но для значений мой SQL терпит неудачу и жалуется на отсутствующие кавычки для кода выше.
Итак, я попытался
String values = list.stream()
.collect(Collectors.joining("','"));
но он терпит неудачу и с этим.Поэтому я сделал обходной путь и добавил еще один оператор с префиксом и суффиксом одной цитаты, и он начал работать.
values = "'"+values+"'";
чтобы быть более конкретным, если я говорю "отдых", "тест" и "лучший" в списке
тогда ожидаемый результат
'rest','test','best'
кто-нибудь знает лучшее решение для этого?
4 ответов
Вы можете использовать Collectors.joining(CharSequence delimiter,CharSequence prefix,CharSequence suffix)
и здесь для API.
String values = list.stream().collect(Collectors.joining("','", "'", "'"));
можно использовать перегрузка Collectors.joining
который принимает параметры префикса и суффикса.
String values = list.stream()
.collect(Collectors.joining("','", "'", "'"));
это правильно разместит одинарные кавычки вокруг всех ваших значений, предполагая, что все ваши значения являются строками, которым нужны одинарные кавычки для синтаксиса.
но, как и в случае со всеми проблемами, связанными с построением запроса путем объединения значений, он оставляет ваш уязвимым для SQL-инъекции. Более надежное и универсальное решение предполагает использование PreparedStatement
. Заполнители значений:?
символы, и вы можете использовать различные setXyz
методы для безопасной установки значений. Он защищает от SQL-инъекций и позволяет использовать любые типы данных, а не только строковые типы.
не создавайте часть "значения", используя конкатенацию строк, поскольку это открывает возможность для атак SQL-инъекций.
Я бы использовал подготовленное заявление здесь. Вы все еще можете построить свой запрос следующим образом:
List<String> columns = Arrays.asList("column1", "column2", "column3");
String columnsFragment = columns.stream().collect(Collectors.joining(","));
String placeholdersFragment = columns.stream().filter(s -> "?").collect(Collectors.joining(","))
String insertStatement = String.format("INSERT INTO ifc.documents (%s) VALUES (%s) ", columnsFragment, placeholdersFragment);
и затем использовать insertStatement
С PreparedStatement
:
PreparedStatement st = connection.prepareStatement(insertStatement);
for (int i = 0; i < values.size(); i++) {
// +1 because prepared statement parameters indices are 1-based
st.setString(i + 1, values.get(i));
}
st.executeUpdate();
в этом случае результирующий запрос будет выглядеть как
INSERT INTO ifc.documents (column1, column2, column3) VALUES (?, ?, ?)
другое использование решения строку.присоединяйтесь метод, как это
String result = "'"+String.join("','", list)+"'";
Function<List<String>,String> function = list2->"'".concat(String.join("','",list2)).concat("'");
System.out.println(function.apply(list));
или использовать сокращение как это
String result = "'"+list.stream().reduce((s, p) -> s + "','" + p).get()+"'";