Именованные запросы 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'...).

Другие вопросы по тегам