grails 域 class 多个循环引用问题
grails domain class multiple circular reference issue
有一个域是其自身的 属性 的情况,如下所示:
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
.
现在,当我创建几个 objects 的 children 组时,说 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()
现在,当我们尝试如下获取经理的 children 时(在我们的 bootstrap 中):
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)]
如何获得预期的输出。
任何帮助都是值得的。
由于您的代码具有自引用 属性(boss) 以及两个相同类型的不同关联属性,Grails 无法创建正确的模式。
来自 Grails 文档:
Occasionally you may find yourself with domain classes that have
multiple properties of the same type. They may even be
self-referential, i.e. the association property has the same type as
the domain class it's in. Such situations can cause problems because
Grails may guess incorrectly the type of the association.
在您的情况下,Grails 正在生成单个 table 并且您的 children 和支持者属性被绑定到架构中的 boss_id 列.
要克服这种情况,您可以使用 mappedBy 并为 children 和支持者 属性 指定 属性 名称以绑定到属性 个名字。
更改域后 class 将如下所示:
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 将为您生成两个 table:groups 和 groups_groups。
如果您为 属性 中的任何一个跳过 mappedBy,那么 属性 将绑定到 'boss_id ' 组中的列 table.
groups_groupstable 的结构为:
+-------------------+----------+---------------------+
| group_children_id | group_id | group_supporters_id |
+-------------------+----------+---------------------+
参考https://grails.github.io/grails-doc/latest/guide/GORM.html#domainClasses了解更多解释。
有一个域是其自身的 属性 的情况,如下所示:
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
.
现在,当我创建几个 objects 的 children 组时,说 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()
现在,当我们尝试如下获取经理的 children 时(在我们的 bootstrap 中):
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)]
如何获得预期的输出。
任何帮助都是值得的。
由于您的代码具有自引用 属性(boss) 以及两个相同类型的不同关联属性,Grails 无法创建正确的模式。
来自 Grails 文档:
Occasionally you may find yourself with domain classes that have multiple properties of the same type. They may even be self-referential, i.e. the association property has the same type as the domain class it's in. Such situations can cause problems because Grails may guess incorrectly the type of the association.
在您的情况下,Grails 正在生成单个 table 并且您的 children 和支持者属性被绑定到架构中的 boss_id 列.
要克服这种情况,您可以使用 mappedBy 并为 children 和支持者 属性 指定 属性 名称以绑定到属性 个名字。
更改域后 class 将如下所示:
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 将为您生成两个 table:groups 和 groups_groups。 如果您为 属性 中的任何一个跳过 mappedBy,那么 属性 将绑定到 'boss_id ' 组中的列 table.
groups_groupstable 的结构为:
+-------------------+----------+---------------------+
| group_children_id | group_id | group_supporters_id |
+-------------------+----------+---------------------+
参考https://grails.github.io/grails-doc/latest/guide/GORM.html#domainClasses了解更多解释。