Grails 如何搜索对另一个域类实例的引用为空或与给定值匹配的域类实例?
为了解释一个Grails示例,我试图获取一个没有作者的书籍列表。作者可以是匿名的,也可以只是未设置(null)。到目前为止,我可以按值搜索,也可以按null搜索,但我似乎无法同时执行这两项操作。以书和作者为例,假设我有以下几本书Grails 如何搜索对另一个域类实例的引用为空或与给定值匹配的域类实例?,grails,gorm,Grails,Gorm,为了解释一个Grails示例,我试图获取一个没有作者的书籍列表。作者可以是匿名的,也可以只是未设置(null)。到目前为止,我可以按值搜索,也可以按null搜索,但我似乎无法同时执行这两项操作。以书和作者为例,假设我有以下几本书 马克·吐温的《汤姆·索耶历险记》 《O:总统小说》匿名作者 “贝奥武夫” 要通过“匿名”查找书籍,我可以这样做 Book.withCriteria { author { eq('name', 'Anonymous') } } Book.withCr
- 马克·吐温的《汤姆·索耶历险记》
- 《O:总统小说》匿名作者
- “贝奥武夫”
Book.withCriteria {
author {
eq('name', 'Anonymous')
}
}
Book.withCriteria {
isNull('author')
}
返回“O:总统小说”
一切都很好。现在要找到没有作者的书,我可以这样做
Book.withCriteria {
author {
eq('name', 'Anonymous')
}
}
Book.withCriteria {
isNull('author')
}
返回“Beowulf”
那也很好。所以要把这两本书都拿来,我应该把它们放在一起
Book.withCriteria {
or {
isNull('author')
author {
eq('name', 'Anonymous')
}
}
}
返回“O:总统小说”
为什么这两本书都不还?我将Grails2.3.7与Hibernate 3.6.10.16结合使用
更新:
我发现了一个有效的查询,尽管我不知道它有什么不同
Book.withCriteria {
or {
isNull('author')
// author {
// eq('name', 'Anonymous')
// }
sqlRestriction('{alias}.author_id = (select author_id from authors where name = ?)', 'Anonymous')
}
}
你有试着做什么吗?看来你只得到了第一个结果
def c = Book.createCriteria()
def list = c.list{
or {
isNull('author')
author {
eq('name', 'Anonymous')
}
}
}
您的第三个查询结果是以下SQL语句(Grails 2.4.4,PostgreSQL): 因此Grails发出了一个内部连接,它消除了所有没有作者的书籍。我不知道Grails是否可能在这里发出一个外部连接
对于使用
sqlRestriction
的第四次查询,这将导致一个子选择:
select ...
from book b
where (b.author_id is null or b.author_id =
(select author_id from author where name = $1))
这是可行的,但一般来说,子选择可能比内部/外部联接慢。如另一个答案中所述,类似这样的关联查询会在SQL级别映射到内部联接。您可以改为使用
createAlias
执行左外部联接:
def list = c.list {
createAlias('author', 'a', CriteriaSpecification.LEFT_JOIN)
or {
isNull('author')
eq('a.name', 'Anonymous')
}
}
是的,这就是问题所在。我不明白为什么它只返回第一个结果,而我希望它同时获取这两个结果。谢谢你的解释,Hibernate可能是一个神秘的野兽。我发现(在Oracle中),无论使用联接还是子查询,查询优化器都会构建相同的查询,我个人认为子查询更易于阅读。