grails 1.3.7 - GORM错误解释可空的反射多对一关系(可能的错误?)

时间:2012-04-24 20:52:37

标签: grails gorm

我遇到了一些事情,起初看来似乎是Gorm中的一个错误(grails 1.3.7)。我想在发布jira问题之前我会在这里发布问题,万一我弄错了。

问题在于:

我有一个域类,它指的是同一个类的父对象,也可以有一个别名的指针,也是同一个域类的。

这是域类:

class Mydomain {
    String name
    Mydomain alias
    Mydomain parent
    Mydomain foo

    static constraints = {
        parent(nullable: true)
        alias(nullable: true)
        foo(nullable: true)
    }
}

如果我执行以下脚本:

Mydomain.list()*.delete()
def one=new Mydomain(name:'one').save()
new Mydomain(name:'two', parent:one).save()

Mydomain.list().each{
    println it.name
    println "parent:${it.parent?.name}"
    println "alias:${it.alias?.name}"
    println "foo:${it.foo?.name}"
    println "============================"
}    

我得到以下结果:

one
parent:null
alias:two
foo:null
============================
two
parent:one
alias:null
foo:null
============================

这意味着当我设置 two.parent = one 时,gorm会设置<​​em> one.alias = 2 。

我想那个gorm这样做是因为它推断 one two 之间存在双向关系,然后设置对象一个引用 two

我可以看到这种行为与Author和Book之间的双向关系一起工作(假设作者当然只写了一本书),但在我的情况下这是危险的,因为gorm去并覆盖一个没有任何关系的关系做到这一点。

所以我的问题是,如何告诉GORM将其视为单向可空关系?

感谢您的任何想法

更新:商业案例

这是我试图建模的商业案例。 公司有一个名称,可以有子公司,仓库,当地办事处等。这是在父母关系的帮助下建模的,有效地创建了一个公司树:

class Company {
    String name
    Company parent
}

现在,这种组织结构的表现形式对每个人来说都不尽相同,有些人可能并不关心办公室层面,也不关心团体层面。这就是公司可以在并行表示中使用别名的原因。它仍然是同一家公司,可以有不同的名称,但您希望能够通过别名关系在这些并行树组织之间导航。

class Company {
    String name
    Company parent
    Company alias
}

所以是的,自我有多种关系,但它们有非常明显的含义,我知道GORM使用最常见的简单情况作为默认情况,但我真的在DSL中尽我所能来指示GORM做正确的事,但没有成功。

这样做的传统方法是使用mappedBy指令添加双向一对多关系:

class Company {
    String name
    Company alias

    static belongsTo=[parent:Company]
    static hasMany=[children:Company]
    static mappedBy=[children:'parent']
}

但是在许多GORM文章中,由于严重的性能问题,这种习惯用语令人气馁。这就是我想要单向关系的原因

Company ---(parent)---> Company

2 个答案:

答案 0 :(得分:1)

这里不应该使用适当的约束吗?只是想知道,因为我做了以下更改,现在输出不同

class Mydomain {
    String name
    Mydomain alias
    Mydomain foo

    static belongsTo = [parent:Mydomain]

    static constraints = {
        parent(nullable: true)
        alias(nullable: true)
        foo(nullable:true)
    }
}

测试输出(可能这是你所期待的)

one
null
null
============================
two
null
null
============================

如果您可以提供有关您的域方案的更多详细信息,我们可以对此进行扩展。另外,GORM,我看到的方式,是自动设置基数,因为没有指定约束。

免责声明:我使用的是Grails 2.0.1

更新(2012年4月26日): 考虑到商业案例的改造,如下所示为你工作?

class Mydomain {
    String name

    static belongsTo = [parent:Mydomain]

    static constraints = {
        parent(nullable: true)
    }
}

class MydomainAlias {

    Mydomain me 
    Mydomain alias

    static constraints = {
        me (unique: 'alias')
    }
}

基本上,这会将别名隔离到另一个表。 Grails会自动为您生成外键依赖项。示例模式导出看起来像这样

create table mydomain (id bigint not null auto_increment, version bigint not null, name varchar(255) not null, parent_id bigint, primary key (id));
create table mydomain_alias (id bigint not null auto_increment, version bigint not null, alias_id bigint not null, me_id bigint not null, primary key (id), unique (alias_id, me_id));
alter table mydomain add index FKECA5F170DF99DE64 (parent_id), add constraint FKECA5F170DF99DE64 foreign key (parent_id) references mydomain (id);
alter table mydomain_alias add index FKA70D16C16A628AB6 (me_id), add constraint FKA70D16C16A628AB6 foreign key (me_id) references mydomain (id);
alter table mydomain_alias add index FKA70D16C1CA5FA6FE (alias_id), add constraint FKA70D16C1CA5FA6FE foreign key (alias_id) references mydomain (id);

答案 1 :(得分:1)

发布JIRA问题后 http://jira.grails.org/browse/GRAILS-9062?focusedCommentId=70641#comment-70641

和邮件列表中的一些交流,

http://markmail.org/message/xcmcclr2lv7ecrbn

Graeme Rocher提出了解决方案。

只需添加以下mappedBy闭包

即可
static mappedBy = [
    parent: 'null',
    alias:'null',
    foo:'null'
]

这将指示GORM不要假设需要双向关系。

感谢所有专家的帮助!