Предоставление переменного числа аргументов хранимой процедуре / SQL

#java #sql #database #hibernate

#java #sql #База данных #переход в спящий режим

Вопрос:

У меня есть некоторая таблица базы данных, скажем, CarTb, и интерфейс, который позволяет просматривать подержанные автомобили, доступные для продажи.

Во внешнем интерфейсе я могу фильтровать столько, сколько мне нравится, — покажите мне все синие машины, покажите мне все красные машины с 4 дверями, покажите мне все машины с регистрационным номером XXX123 Или возможностью подключения ipod и стереосистемой с пятью динамиками. и т.д.

Что я хочу иметь возможность делать на серверной части Java, так это создавать систему, которая запрашивает базу данных динамически на основе того, что отправляет мне пользовательский интерфейс. Мне интересно, возможно ли динамически вводить целую строку аргументов в хранимый процесс… Очевидно, я знаю, что вы можете сопоставлять отдельные аргументы, такие как doors =? и цвет=? а затем подставьте значения… Но как насчет переменных аргументов, я полагаю, почти как Java vargs.

Вы всегда будете выполнять select * из CarTb, это просто предложение where может быть любым из следующих…

  • ГДЕ doors=4
  • ГДЕ doors = 5, color = RED И MP3 = Y
  • ГДЕ turbo=Y ИЛИ blowned=Y

Вы поняли идею.

Есть предложения? У нас есть доступ к hibernate, если это поможет, и к базе данных sybase (т. Е. мы можем написать другой хранимый процесс, чтобы сделать это, если необходимо).

—Приветствия, Дэйв

Комментарии:

1. Есть ли у вас доступ к базе данных (например, не могли бы вы написать хранимую процедуру), или вы ограничены использованием Java?

2. Да… Я отредактировал исходный вопрос, чтобы отразить это.

Ответ №1:

Вы можете динамически создавать свой запрос, но все еще должны doors=:param . Например:

 if (doorsSelected) {
    clauses.add("doors=:doors");
    paramNames.add("doors");
    values.add(doors);
}

if (engineSelected) {
    clauses.add("engine=:engine");
    params.put("engine", engine);
}
  

Затем просто присоединитесь к списку предложений (например, используя Joiner от guava):

 String queryString = Joiner.on(" AND ").join(clauses);
Query query = session.createQuery(queryString);
  

Затем выполните итерацию params и query.setParameter(key, value)

Комментарии:

1. Хм… Кажется, неплохая идея. Учитывая, что у нас могут быть всевозможные опции (т. Е. не только AND), разве нам не нужно было бы выполнить какой-то пользовательский синтаксический анализ, чтобы определить, где разместить AND, OR, NOT и т.д. По мере необходимости?

2. что ж, вы можете объединить их в StringBuilder , если хотите. Или иметь отдельные списки для andClauses, orClauses и т.д.

Ответ №2:

Я могу придумать один способ обмана, хотя я предполагаю / надеюсь, что запрос будет оптимизирован. Вы могли бы добавить дополнительные аргументы в свой подготовленный оператор для условий, которые вы хотели бы добавить, которые будут оцениваться как true, только если поле присутствовало.

 select ... 
  from ...
    where var1=? and <expression associated with that var1>  
    or var2=? and <expression associated with that var2>  
    or etc