Именованные запросы Grails не работают с оператором "in"
У меня есть приложение Grails (2.2.4). Где в доменном классе у меня выглядит вот так
class Author implements Serializable {
....
static hasMany = [
book : Book
]
static namedQueries = {
hasGenre {genreNameList ->
book{
genres {
'title' in genreNameList
}
}
}
}
}
class Book implements Serializable{
Author author
Genres genres
static belongsTo = [author: Author , genre: Genres ]
static mapping = {
.....
author lazy: false
}
}
class Genres implements Serializable{
String title
}
Если я выполню запрос, как показано ниже, будут извлечены все значения, а не только Авторы с по крайней мере одной книгой с жанром в genereNameList
String comaSeperatedGenereName = "genere1,genere2"
def genereNameList = comaSeperatedGenereName.split(",")
Author.hasGenre(genereNameList)
Но если я изменю namedQuery, как показано ниже,
hasGenre {genreName ->
book{
genres {
eq 'title' , genreName
}
}
И если я передаю строку, как следует
Author.hasGenre('genere1')
Это работает как ожидалось. Есть что-то, чего мне не хватает?
заранее спасибо
2 ответа
В операторе есть отличное представление, и я подозреваю, что вместо критериев вы получаете отличное в операторе.
Попробуйте изменить код на
static namedQueries = {
hasGenre {genreNameList ->
book{
genres {
'in' 'title', genreNameList
}
}
}
}
Нюанс между запросами критериев и собственными запросами, такими как SQL, заключается в том, что запрос критериев не является фактическим запросом. Это построитель запросов.
Другими словами, запрос критерия не выполняется в том же смысле, что и запрос SQL в базе данных SQL. Вместо этого выполняется запрос критерия для создания запроса к базе данных. Имея это в виду, легче увидеть, что пошло не так.
hasGenre {genreNameList ->
book{
genres {
'title' in genreNameList
}
}
}
Выражение 'title' in genreNameList
возвращает логическое значение. Он не влияет на запрос критерия, поскольку не вызывается ни один из методов построения запроса критерия. Таким образом, в конце концов запрос строится так, чтобы вернуть все.
Эквивалентом Groovy в ключевом слове в запросе критериев является in()
метод.
hasGenre {genreNameList ->
book{
genres {
'in'('title', genreNameList)
}
}
}
Это создает запрос, который вы ожидаете. Тем не менее, потому что in
является ключевым словом в Groovy, чтобы выполнить метод, его имя должно быть заключено в кавычки. Я думаю, что более эстетически приятный способ достичь того же inList()
метод.
hasGenre {genreNameList ->
book{
genres {
inList('title', genreNameList)
}
}
}
Наконец, чтобы лучше проиллюстрировать концепцию строителя, вот более подробный способ выполнить то же самое.
hasGenre {genreNameList ->
book{
genres {
or {
genreNameList.each {
eq('title', it)
}
}
}
}
}
Этот запрос строится путем вызова eq()
за название каждого жанра. Конечным результатом является запрос с несколькими или соединениями (например, title = 'foo' или title = 'bar'...).