我有一个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
中至少有一本具有genere的书的Authors值String comaSeperatedGenereName = "genere1,genere2"
def genereNameList = comaSeperatedGenereName.split(",")
Author.hasGenre(genereNameList)
但是如果我像下面这样改变namedQuery,
hasGenre {genreName ->
book{
genres {
eq 'title' , genreName
}
}
如果我传递一个像这样的字符串
Author.hasGenre('genere1')
按预期工作。我是不是漏掉了什么?
Thanks in advance
有一个groovy in操作符,我怀疑你得到的不是标准,而是groovy in操作符。
尝试将代码更改为
static namedQueries = {
hasGenre {genreNameList ->
book{
genres {
'in' 'title', genreNameList
}
}
}
}
标准查询和本地查询(如SQL)之间的细微差别是,标准查询不是实际的查询。它是一个查询生成器。
换句话说,标准查询不像在SQL数据库中运行SQL查询那样运行。相反,执行一个标准查询以生成一个数据库查询。考虑到这一点,就更容易看出哪里出了问题。
hasGenre {genreNameList ->
book{
genres {
'title' in genreNameList
}
}
}
表达式'title' in genreNameList
返回一个布尔值。它对标准查询没有影响,因为没有调用任何标准查询的构建器方法。因此,最后构造的查询将返回所有内容。
在标准查询中,与Groovy的in关键字等价的是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'…)。