PreparedStatement В альтернативах пункта?

Исключение нулевого указателя генерируется, когда приложение пытается использовать null в случае, когда требуется объект. К ним относятся:

  1. Вызов метода экземпляра объекта null.
  2. Доступ или изменение поля объекта null.
  3. Принимая длину null, как если бы это был массив.
  4. Доступ или изменение слотов null, как если бы это был массив.
  5. Бросок null как будто это было значение Throwable.

Приложения должны бросать экземпляры этого класса, чтобы указать на другие незаконные использования объекта null.

Ссылка: http://docs.oracle.com/javase/8/docs/api/java/lang/NullPointerException.html

328
задан Jonas 30 August 2011 в 07:54
поделиться

9 ответов

Анализ доступных различных вариантов, и за и против каждого доступен здесь .

предложенные опции:

  • Готовят SELECT my_column FROM my_table WHERE search_column = ?, выполняют его для каждого значения и ОБЪЕДИНЕНИЯ клиентские результаты. Требует только одного подготовленного оператора. Медленный и болезненный.
  • Готовят SELECT my_column FROM my_table WHERE search_column IN (?,?,?) и выполняют его. Требует, чтобы тот подготовил оператор на size-of-IN-list. Быстрый и очевидный.
  • Готовят SELECT my_column FROM my_table WHERE search_column = ? ; SELECT my_column FROM my_table WHERE search_column = ? ; ... и выполняют его. [Или используйте UNION ALL вместо тех точек с запятой. - редактор] Требует, чтобы тот подготовил оператор на size-of-IN-list. Глупо медленный, строго хуже, чем WHERE search_column IN (?,?,?), таким образом, я не знаю, почему блоггер даже предложил его.
  • Использование хранимая процедура для построения набора результатов.
  • Готовят различные запросы size-of-IN-list N; скажите, с 2, 10, и 50 значений. Для поиска В СПИСКЕ с 6 различными значениями заполните размер 10 запросов так, чтобы это было похоже SELECT my_column FROM my_table WHERE search_column IN (1,2,3,4,5,6,6,6,6,6). Любой достойный сервер оптимизирует дублирующиеся значения прежде, чем выполнить запрос.

Ни одна из этих опций не является супер большой, все же.

на Дублирующиеся вопросы ответили в этих местах с одинаково нормальными альтернативами, тем не менее ни один из них супер большой:

Правильный Ответ при использовании JDBC4 и сервера, который поддерживает x = ANY(y), должен использовать PreparedStatement.setArray, как описано здесь:

, кажется, нет никакого способа сделать setArray работа с В СПИСКАХ, все же.

<час>

Иногда SQL-операторы загружаются во времени выполнения (например, из файла свойств), но требуют переменного количества параметров. В таких случаях сначала определите запрос:

query=SELECT * FROM table t WHERE t.column IN (?)

Затем, загружают запрос. Тогда определите количество параметров до выполнения его. Как только количество параметра известно, выполняется:

sql = any( sql, count );

, Например:

/**
 * Converts a SQL statement containing exactly one IN clause to an IN clause
 * using multiple comma-delimited parameters.
 *
 * @param sql The SQL statement string with one IN clause.
 * @param params The number of parameters the SQL statement requires.
 * @return The SQL statement with (?) replaced with multiple parameter
 * placeholders.
 */
public static String any(String sql, final int params) {
    // Create a comma-delimited list based on the number of parameters.
    final StringBuilder sb = new StringBuilder(
            new String(new char[params]).replace("\0", "?,")
    );

    // Remove trailing comma.
    sb.setLength(Math.max(sb.length() - 1, 0));

    // For more than 1 parameter, replace the single parameter with
    // multiple parameter placeholders.
    if (sb.length() > 1) {
        sql = sql.replace("(?)", "(" + sb + ")");
    }

    // Return the modified comma-delimited list of parameters.
    return sql;
}

Для определенных баз данных, где передача массива через спецификацию JDBC 4 не поддерживается, этот метод может упростить преобразование медленного = ? в быстрее IN (?) условие пункта, которое может тогда быть расширено путем вызова any метод.

186
ответ дан Dave Jarvis 23 November 2019 в 00:48
поделиться

Идея следующего Adam. Сделайте свой подготовленный вид оператора выбора my_column от my_table, где search_column в (#) Создают Строку x и заполняют его многими"???" в зависимости от Вашего списка значений Тогда просто изменяют # в запросе для Вашей новой Строки x заполнение

0
ответ дан 23 November 2019 в 00:48
поделиться

Только для полноты: Пока набор значений не является слишком большим, Вы могли также просто строковая конструкция оператор как

... WHERE tab.col = ? OR tab.col = ? OR tab.col = ?

, который Вы могли тогда передать, чтобы подготовиться (), и затем использовать setXXX () в цикле для устанавливания всех значений. Это смотрит yucky, но много "больших" коммерческих систем обычно делают такого рода вещь, пока они не поражают определенные для DB пределы, такие как 32 КБ (я думаю, что это) для операторов в Oracle.

, Конечно, необходимо удостовериться, что набор никогда не будет необоснованно большим, или делать обнаружение ошибок, если это.

0
ответ дан Carl Smotricz 23 November 2019 в 00:48
поделиться

Никаким простым путем AFAIK. Если цель должна поддержать отношение кэша оператора на высоком уровне (т.е. не создать оператор на каждое количество параметра), можно сделать следующее:

  1. создают оператор с некоторыми (например, 10) параметры:

    ... ГДЕ В (??????????)...

  2. Связывают все фактические параметры

    setString (1, "нечто"); setString (2, "панель");

  3. Связывают остальных как ПУСТОЙ УКАЗАТЕЛЬ

    setNull (3, Типы. VARCHAR)... setNull (10, Типы. VARCHAR)

ПУСТОЙ УКАЗАТЕЛЬ никогда ничему не соответствует, таким образом, это оптимизировано планом SQL разработчик.

логику легко автоматизировать при передаче Списка в функцию ДАО:

while( i < param.size() ) {
  ps.setString(i+1,param.get(i));
  i++;
}

while( i < MAX_PARAMS ) {
  ps.setNull(i+1,Types.VARCHAR);
  i++;
}
18
ответ дан Vladimir Dyuzhev 23 November 2019 в 00:48
поделиться

Неприятное обходное решение, но конечно выполнимый должно использовать вложенный запрос. Составьте временную таблицу MYVALUES со столбцом в нем. Вставьте свой список значений в таблицу MYVALUES. Тогда выполнитесь

select my_column from my_table where search_column in ( SELECT value FROM MYVALUES )

Ужасный, но жизнеспособная альтернатива, если Ваш список значений является очень большим.

Эта техника имеет добавленное преимущество потенциально лучших планов запросов от оптимизатора (проверьте страницу на несколько значений, сканирование таблицы только однажды вместо этого однажды на значение, и т.д.), может экономить наверху, если Ваша база данных не кэширует подготовленные операторы. Ваши "ВСТАВКИ" должны были бы быть сделаны в пакете, и таблица MYVALUES, возможно, должна быть настроена для имения минимальной блокировки или других высоко-служебных мер защиты.

10
ответ дан James Schek 23 November 2019 в 00:48
поделиться

Я никогда не пробовал его, но был бы, .setArray () делают то, что Вы ищете?

Обновление : Очевидно нет. setArray только, кажется, работает с java.sql. Массив, который прибывает из столбца ARRAY, который Вы получили от предыдущего запроса или подзапроса со столбцом ARRAY.

5
ответ дан Paul Tomblin 23 November 2019 в 00:48
поделиться

Я предполагаю, что Вы могли (использование основной обработки строк) генерируют строку запроса в PreparedStatement для имения многих ? соответствие количеству объектов в списке.

, Конечно, при выполнении этого Вы - просто шаг далеко от генерации гиганта, объединенного в цепочку OR в Вашем запросе, но не имея правильного количества ? в строке запроса, я не вижу, как еще можно работать вокруг этого.

3
ответ дан Adam Bellaire 23 November 2019 в 00:48
поделиться

попытаться использовать функцию instr?

select my_column from my_table where  instr(?, ','||search_column||',') > 0

тогда

ps.setString(1, ",A,B,C,"); 

По общему признанию это - определенный грязный взлом, но он действительно уменьшает возможности для внедрения SQL. Работы в оракуле так или иначе.

1
ответ дан stjohnroe 23 November 2019 в 00:48
поделиться

Сгенерируйте строку запроса в Предварительном Составе, чтобы количество ?s совпадало с количеством элементов в вашем списке. Вот пример:

public void myQuery(List<String> items, int other) {
  ...
  String q4in = generateQsForIn(items.size());
  String sql = "select * from stuff where foo in ( " + q4in + " ) and bar = ?";
  PreparedStatement ps = connection.prepareStatement(sql);
  int i = 1;
  for (String item : items) {
    ps.setString(i++, item);
  }
  ps.setInt(i++, other);
  ResultSet rs = ps.executeQuery();
  ...
}

private String generateQsForIn(int numQs) {
    String items = "";
    for (int i = 0; i < numQs; i++) {
        if (i != 0) items += ", ";
        items += "?";
    }
    return items;
}
0
ответ дан 23 November 2019 в 00:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: