我使用Grails 2.2.4(Grails 2.3.11中的相同行为)并拥有引用域类B的域类A
class A {
static hasOne = [b: B]
static constraints = { b nullable: true }
}
class B {
static belongsTo = [a: A]
}
我试图找到A的所有具有B的实例。
A.findAllByBIsNotNull()*.b
返回B和null的列表:
[null, null, b1, b2, null, ...]
怎么样?
如果我使用
,也会发生同样的情况A.withCriteria {
isNotNull 'b'
}*.b
我做错了什么?
更新
我意识到问题是因为hasOne
。如果不是static hasOne = [b: B]
,而是B b
,则可行。前者将外键移动到表B,后者在表A中创建外键关系。
那么为什么查询在前一种情况下不起作用?如何在外键在B范围内时查询所有A
s,而不是B
?
答案 0 :(得分:4)
由于@Koloritnij的评论和@Alexander Suraphel的修改后的答案,我终于解决了它。 谢谢你。
如果外键位于B
表上(由于hasOne
),以下两个查询解决了这种情况:
使用A
s查找所有B
:( b
不是null
):
A.withCriteria {
b {}
}
这会产生内部联接:SELECT * FROM a INNER JOIN b ON a.id=b.a_id;
在没有 A
的情况下找到所有B
s (b
为null
):
A.withCriteria {
createAlias('b', 'bAlias', CriteriaSpecification.LEFT_JOIN)
isNull 'bAlias.id'
}
这导致左外连接:SELECT * FROM a LEFT OUTER JOIN b ON a.id=b.a_id WHERE b.id IS NULL;
答案 1 :(得分:1)
更新后:
使用B
中的一个字段。让我们说B
有字段name
:
A.withCriteria { b { isNotNull("name") }}*.b
旧答案:
问题可能出在B类的toString()
。
添加
String toString() {
getClass().name
}
到班级B
并尝试重新运行查询。
答案 2 :(得分:0)
如果你只需要服用B,为什么你不能使用:
B.findAll()
或者如果是A:
B.findAllByA(a)
<强> UPD:强> 使用标准:
A.createCriteria().list{
isNotNull 'B'
isNull 'C'
}
或者这是个坏主意但必须奏效:
def bList = B.createCriteria().list{
projections{
property 'id'
}
A.createCriteria().list{
b{
'in' ('id',bList)
}
}
答案 3 :(得分:0)
为了将来参考,任何想要做同样事情但使用 GORM Where 查询或 DetachedCriteria 的人,其等效项如下:
def criteria = new DetachedCriteria(A)
criteria.where {
join('b', JoinType.LEFT)
b {
isNull 'id'
}
}.list()
答案 4 :(得分:-1)
不应该这样
A.findAllBybIsNotNull()*.b
(注意小写字母b)?
或
A.findAll("from A as a where a.b is null")