Подтвердить что ты не робот

Аномальные динамические фильтры

Я изучаю небольшую документацию по анормам (из игровой среды), и неясно, поддерживает ли она обычный случай использования запроса: динамические фильтры, то есть пользователь заполняет 2 или 3 критерия поиска в форме поиска 10 полей.

В этом случае, как я могу динамически построить запрос без классической манипуляции с строкой?

4b9b3361

Ответ 1

Да, я думаю, что вопрос, на который ссылается Робин Грин, содержит ответ. Просто укажите свой запрос со всеми возможными критериями с помощью заполнителей (например, {criterion1}) и вызовите метод on() в запросе, передав фактические параметры Seq из Option, как описано в принятом ответе.


Модифицированный пример из документа Anorm, если у вас есть два критерия, но вы хотите, чтобы ваш запрос фильтровал код страны, а не в столице:

SQL(
"""
select * from Country c 
join CountryLanguage l on l.CountryCode = c.Code 
where ({countryCode} is null or c.code = {countryCode})
  and ({capital} is null or c.capital = {capital});
"""
).on("countryCode" -> Some("FRA"), "capital" -> None)

Это должно сделать трюк.

Ответ 2

Короткий ответ первым. Предположим, у вас есть таблица в базе данных, содержащая 3 столбца: name, email, pass. Но от пользователя вы получили только name и password, но не email. Так что сделайте опции всех 3

val name:Option[String] = Some("alice")
val email:Option[String] = None
val pass:Option[String] = Some("password")

//For db insertion have this:

  DB.withConnection { implicit conn =>
  SQL("INSERT INTO USERS (name,email,pass) VALUES ({n},{e},{p})").on(
 'n -> name, 'e -> email,'p -> pass).executeInsert()
 }

Выполняя вышеуказанное, поскольку email - None, он будет вставлять null в вашу базу данных. Поэтому в вашем случае для всех ваших 10 столбцов вы можете определить их в инструкции SQL выше и передать Option в on(). Если какой-либо из них None, то он примет его как null в базе данных.

Хотя может быть проблема, если есть ограничение на столбец в вашей схеме как NOT NULL. В этом случае вы можете использовать getOrElse для таких столбцов, как ниже:

DB.withConnection { implicit conn =>
  SQL("INSERT INTO USERS (name,email,pass) VALUES ({n},{e},{p})").on(
 'n -> name, 'e -> email.getOrElse("Default Email"),'p -> pass).executeInsert()

Ниже представлен список того, как воспроизведение преобразует тип в тип базы данных. Его можно найти в объекте anorm.ToStatement:

        case Some(bd: java.math.BigDecimal) => stmt.setBigDecimal(index, bd)
        case Some(o) => stmt.setObject(index, o)
        case None => stmt.setObject(index, null)
        case bd: java.math.BigDecimal => stmt.setBigDecimal(index, bd)
        case date: java.util.Date => stmt.setTimestamp(index, new java.sql.Timestamp(date.getTime()))
        case o => stmt.setObject(index, o)

Вы видите, что для None он принимает значение null.


В случае SELECT hmm, я не знаю какой-либо функции анормальности, которая здесь помогает, но я думаю, что простая манипуляция строками может быть достаточной:

def getColumns(xs:List[Option[_]]):String = {
    val notNone = xs.collect{
       case Some(x) => x.toString
    }
    notNone.mkString(",")
}

И затем SQL("SELECT %s from table".format(getColumns(List(nameColumn,emailColumn,passColumn))).

Хотя это не то, что вы хотите. Anorm - это просто библиотека зданий sql. Чтобы сделать то, что вы хотите, он также должен будет помнить вашу схему таблиц (то есть имена наименьших столбцов..). Я не думаю, что аномалия сделана для всего этого.

Ответ 3

Anorm, по-видимому, очищает работу в предпосылке, что вы вставляете простой старый SQL без каких-либо функций, таких как typesafety или query building. Вероятно, это не правильный инструмент для динамических запросов. Построение запросов в конечном итоге должно быть манипуляцией с строками, поэтому я бы рекомендовал использовать библиотеку, которая сделает это за вас. Интегрировать любую библиотеку для генерации операторов SQL с помощью Anorm должно быть легко.

Вы можете динамически построить запрос и передать эту строку запроса в Anorm с библиотекой, например jOOQ. В качестве бонуса вы получите поддержку многих баз данных. jOOQ кажется популярным, но, вероятно, есть много других библиотек, которые вы могли бы использовать вместо этого. Или полностью замените Anorm, если он не подходит для вашего проекта.