Grails 命名查询不适用于 "in" 语句

Grails named queries not working with "in" statement

我有一个 Grails 应用程序 (2.2.4)。我在域 class 中的哪个地方看起来像这样

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

中至少有一本带有 genere 的书的作者
String comaSeperatedGenereName = "genere1,genere2"
def genereNameList = comaSeperatedGenereName.split(",")
Author.hasGenre(genereNameList)

但是如果我像下面这样更改 namedQuery,

      hasGenre {genreName -> 
            book{
               genres {  
                   eq 'title' , genreName 
           } 
       }

如果我像下面这样传递一个字符串

Author.hasGenre('genere1')

这按预期工作。我有什么遗漏吗?

提前致谢

operator 中有一个 groovy,我怀疑你得到的不是标准中的 groovy in operator.

尝试将您的代码更改为

  static namedQueries = {
      hasGenre {genreNameList -> 
            book{
               genres {  
              'in'  'title', genreNameList 
           } 
       }
   }
  }

条件查询和 SQL 等本机查询之间的细微差别是条件查询不是实际查询。这是一个查询 builder

换句话说,条件查询在 运行 与 SQL 查询 运行 中的意义不同SQL 数据库。相反,执行标准查询以 生成 数据库查询。考虑到这一点,就更容易看出哪里出了问题。

hasGenre {genreNameList -> 
    book{
       genres {  
           'title' in genreNameList 
       }
   } 
}

表达式 'title' in genreNameList return 是一个布尔值。它对条件查询没有影响,因为 none 的条件查询的构建器方法被调用。所以最后查询构造为 return everything.

条件查询中 Groovy 关键字的等价物是 in() 方法。

hasGenre {genreNameList -> 
    book{
       genres {  
           'in'('title', genreNameList)
       }
   } 
}

这构建了您期望的查询。但是,因为 in 是 Groovy 中的关键字,为了执行该方法,必须引用其名称。我认为 aesthetically-pleasing 完成同样事情的方法是 inList() 方法。

hasGenre {genreNameList -> 
    book{
       genres {  
           inList('title', genreNameList)
       }
   } 
}

最后,为了更好地说明构建器的概念,这里有一个更详细的方法来完成同样的事情。

hasGenre {genreNameList -> 
    book{
       genres {  
           or {
               genreNameList.each {
                   eq('title', it)
               }
           }
       }
   } 
}

此查询是通过为每个流派标题调用 eq() 构建的。最终结果是具有多个 连词的查询(例如 title = 'foo' 或 title = 'bar'...)。