【问题标题】:Grails GORM query for null hasOne association fails空 hasOne 关联的 Grails GORM 查询失败
【发布时间】:2014-11-24 17:03:59
【问题描述】:

我使用 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]
}

我尝试查找所有具有 B 的 A 实例。

A.findAllByBIsNotNull()*.b

返回 B 和空值列表:

[null, null, b1, b2, null, ...]

怎么样?

如果我使用也会发生同样的情况

A.withCriteria {
    isNotNull 'b'
}*.b

我做错了什么?

更新:

我意识到问题出在hasOne。如果不是static hasOne = [b: B],而是B b,它可以工作。前者将外键移动到表 B,后者在表 A 中创建外键关系。 那么为什么在前一种情况下查询不起作用,当外键在 B 内时,我如何查询所有 As,没有 B

【问题讨论】:

  • 如果你打电话给println A.findAllByBIsNotNull()*.b*.id会发生什么?

标签: grails grails-orm


【解决方案1】:

感谢@Koloritnij 的评论和@Alexander Surapel 的修改答案,我终于解决了。 谢谢。

如果外键在B表上(由于hasOne),下面两个查询解决了这种情况:

查找所有As 和Bs:(b 不是null):

A.withCriteria {
  b {}
}

这会导致内部连接:SELECT * FROM a INNER JOIN b ON a.id=b.a_id;

找到所有As 没有 Bs(bnull):

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 回答您的问题!考虑投票和/或接受其他答案。
【解决方案2】:

更新后:

使用B 中的字段之一。假设B 有字段name

A.withCriteria { b { isNotNull("name") }}*.b

旧答案:

问题可能出在 B 类的toString()

添加

String toString() { 
    getClass().name
}

到 Class B 并尝试再次运行您的查询。

【讨论】:

  • 很有创意,但没有。 Java 以适当的方式实现了默认的toString。 Groovy 并没有改变这一点。
【解决方案3】:

为了将来的参考,任何想要做同样事情但使用 GORM Where 查询或 DetachedCriteria 的人,等效如下:

def criteria = new DetachedCriteria(A)
criteria.where {
    join('b', JoinType.LEFT)
    b {
        isNull 'id'
    }
}.list()

【讨论】:

    【解决方案4】:

    如果你只需要拿B,为什么你不能用:

    B.findAll()
    

    或者如果通过 A:

     B.findAllByA(a)
    

    统一更新: 使用标准:

        A.createCriteria().list{
           isNotNull 'B'
           isNull 'C'
        }
    

    或者这是个坏主意,但必须有效:

    def bList = B.createCriteria().list{
        projections{
           property 'id'
        }
        A.createCriteria().list{
          b{
           'in' ('id',bList)
          }
        }
    

    【讨论】:

    • 本例为简化案例。我真正想要的是A.findAllByBIsNotNullAndCIsNull(),然后遍历所有As。
    • A.createCriteria().list { isNotNull 'b' }*.b 返回[null, null, null, ...]
    • A.createCriterya().list{b{isNotNull 'id'}}*.b 这是我最后的想法
    • 确实解决了!它导致AB 的内部连接,因此只返回带有B 的A。不幸的是,没有B 就无法查询所有As。我也需要这样做......
    【解决方案5】:

    不应该这样吗 A.findAllBybIsNotNull()*.b(注意小写b)?

    或者

    A.findAll("from A as a where a.b is null")

    【讨论】:

    • B 应为大写(参见grails.org/doc/2.2.4/guide/GORM.html#finders 中的示例,例如字符串标题 -> findByTitle...)A.findAll("from A as a where a.b is null")*.b 返回一个空列表。 A.findAll("from A as a where a.b is not null")*.b 返回一个包含空值和非空值的列表。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-24
    • 1970-01-01
    相关资源
    最近更新 更多