如何搜索域 class 实例,其中对另一个实例的引用为空或与给定值匹配?
How can I search for domain class instances where a reference to another one is empty or matches a given value?
套用一个 Grails 示例,我正在尝试获取没有作者的书籍列表。作者可以是匿名的,或者根本没有设置(null)。到目前为止,我可以按值搜索,也可以按 null 进行搜索,但我似乎无法同时执行这两项操作。使用书籍和作者示例,假设我有以下书籍...
- "The Adventures of Tom Sawyer" 马克·吐温
- "O: A Presidential Novel" 来自匿名
- "Beowulf"
要查找 "Anonymous" 的书籍,我可以这样做...
Book.withCriteria {
author {
eq('name', 'Anonymous')
}
}
Returns "O: A Presidential Novel"
一切顺利。现在要查找没有作者的书,我可以这样做...
Book.withCriteria {
isNull('author')
}
Returns "Beowulf"
这也很好。所以要拿两本书我应该 'or' 他们在一起...
Book.withCriteria {
or {
isNull('author')
author {
eq('name', 'Anonymous')
}
}
}
Returns "O: A Presidential Novel"
为什么这 return 两本书都没有?我正在使用 Grails 2.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')
}
}
}
您的第 3 个查询结果在此 SQL 语句中(Grails 2.4.4,PostgreSQL):
select ...
from book b inner join author a on b.author_id = a.id
where (b.author_id is null or (a.name=))
所以 Grails 发出了一个 inner join,它消除了所有没有作者的书。我不知道 Grails 是否有可能在此处发出 outer join。
至于您使用 sqlRestriction
的第 4 个查询,结果是 sub select:
select ...
from book b
where (b.author_id is null or b.author_id =
(select author_id from author where name = ))
所以这可行,但一般来说子 selects 可能比 inner/outer 连接慢。
正如在另一个答案中提到的,类似的关联查询映射到 SQL 级别的内部联接。您可以改为使用 createAlias
:
进行左外连接
def list = c.list {
createAlias('author', 'a', CriteriaSpecification.LEFT_JOIN)
or {
isNull('author')
eq('a.name', 'Anonymous')
}
}
套用一个 Grails 示例,我正在尝试获取没有作者的书籍列表。作者可以是匿名的,或者根本没有设置(null)。到目前为止,我可以按值搜索,也可以按 null 进行搜索,但我似乎无法同时执行这两项操作。使用书籍和作者示例,假设我有以下书籍...
- "The Adventures of Tom Sawyer" 马克·吐温
- "O: A Presidential Novel" 来自匿名
- "Beowulf"
要查找 "Anonymous" 的书籍,我可以这样做...
Book.withCriteria {
author {
eq('name', 'Anonymous')
}
}
Returns "O: A Presidential Novel"
一切顺利。现在要查找没有作者的书,我可以这样做...
Book.withCriteria {
isNull('author')
}
Returns "Beowulf"
这也很好。所以要拿两本书我应该 'or' 他们在一起...
Book.withCriteria {
or {
isNull('author')
author {
eq('name', 'Anonymous')
}
}
}
Returns "O: A Presidential Novel"
为什么这 return 两本书都没有?我正在使用 Grails 2.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')
}
}
}
您的第 3 个查询结果在此 SQL 语句中(Grails 2.4.4,PostgreSQL):
select ...
from book b inner join author a on b.author_id = a.id
where (b.author_id is null or (a.name=))
所以 Grails 发出了一个 inner join,它消除了所有没有作者的书。我不知道 Grails 是否有可能在此处发出 outer join。
至于您使用 sqlRestriction
的第 4 个查询,结果是 sub select:
select ...
from book b
where (b.author_id is null or b.author_id =
(select author_id from author where name = ))
所以这可行,但一般来说子 selects 可能比 inner/outer 连接慢。
正如在另一个答案中提到的,类似的关联查询映射到 SQL 级别的内部联接。您可以改为使用 createAlias
:
def list = c.list {
createAlias('author', 'a', CriteriaSpecification.LEFT_JOIN)
or {
isNull('author')
eq('a.name', 'Anonymous')
}
}