【问题标题】:grails domain class multiple circular reference issuegrails域类多循环引用问题
【发布时间】:2015-08-07 06:29:50
【问题描述】:

有一个域一直是其自身属性的情况,如下所示:

Group{
    String name
    Role role
    static belongsTo=[boss:Group]
    static hasMany=[children:Group,supporters:Group]
}

static constraint={
     boss nullable:true
     supporters validator: {supporters, group->
            supporters?.each {Group supplier ->
                if(!(supporters.role == Role.OPS)){
                    return "domain.not.supporters.object"
                }
            }
            return true
        }
}
}

Role{
   MANAGER,LEADER,DEVELOPERS,OPS
}

以上支持者的角色是 OPS,我们也为其添加了验证。总体支持者不属于原始Manager>Leader>Developer hierarchy

现在,当我创建一些儿童组对象时说MANAGER_RAD > LEAD_BAD ->( DEV_JACK and DEV_MOHAN),并且支持者只提供给经理。下面的代码将使您理解该场景:

Group manager = new Group(name:'MANAGER_RAD')
manager.addToSupporters(new Group(name:'OPS_BISK').save(flush:true))
manager.addToSupporters(new Group(name:'OPS_BAHADUR').save(flush:true))
Group lead = new Group(name:'LEAD_BAD').save(flush:true)
lead.addToChildren(new Group(name:'DEV_JACK').save(flush:true))
lead.addToChildren(new Group(name:'DEV_MOHAN').save(flush:true))
lead.save(flush:true)
manager.addToChildren(lead)
manager.save()

现在,当我们尝试按如下方式获取经理的孩子时(比如在我们的引导程序中):

Group manager = Group.findByName('MANAGER_RAD')
println "------Manager team members---->$manager.children"
println "------supporters for Manager---->$manager.supporters"

预期的输出是:

------Manager team members---->[LEAD_BAD(id:2)]
------supporters for Manager---->[OPS_BAHADUR(id:7),OPS_BISK(id:7)]

但是返回的输出是:

------Manager team members---->[LEAD_BAD(id:2),OPS_BAHADUR(id:7),OPS_BISK(id:7)]
------supporters for Manager---->[LEAD_BAD(id:2),OPS_BAHADUR(id:7),OPS_BISK(id:7)]

我怎样才能得到预期的输出。

任何帮助都是值得的。

【问题讨论】:

标签: java hibernate grails grails-orm grails-2.0


【解决方案1】:

由于您的代码具有自引用属性(boss)以及两个相同类型的不同关联属性,Grails 无法创建正确的架构。

来自 Grails 文档:

有时您可能会发现自己的域类具有 同一类型的多个属性。他们甚至可能是 自引用,即关联属性与 它所在的域类。这种情况可能会导致问题,因为 Grails 可能会错误地猜测关联的类型。

在您的情况下,Grails 正在生成一个表,并且您的 children 和 supporters 属性被绑定到架构中的 boss_id 列。

要克服这种情况,您可以使用 ma​​ppedBy 并指定要绑定到属性名称的子属性和支持者属性的属性名称。

更改后,您的域类将如下所示:

class Group {
    String name
    Role role

    static belongsTo = [boss: Group]
    static hasMany = [children: Group, supporters: Group]

    static mapping = {
        table 'groups'
    }

    static mappedBy = [children  : "none",
                       supporters: "none"]

    static constraints = {
        boss nullable: true
        role nullable: true
        supporters validator: { supporters, group ->
            supporters?.each { Group supplier ->
                if (supporters.role != Role.OPS) {
                    return "domain.not.supporters.object"
                }
            }
            return true
        }
    }

}

enum Role {
    MANAGER, LEADER, DEVELOPERS, OPS
}

现在 Grails 将为您生成两个表:groups 和 groups_groups。 如果您为任一属性跳过 ma​​ppedBy,该属性将绑定到 groups 表中的“boss_id”列。

groups_groups 表的结构是:

+-------------------+----------+---------------------+
| group_children_id | group_id | group_supporters_id |
+-------------------+----------+---------------------+

更多解释请参考https://grails.github.io/grails-doc/latest/guide/GORM.html#domainClasses

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多