grails hasOne vs直接成员变量



假设我有一个grails域类,看起来像

class Person {
Address address
}

我也可以宣布它为

class Person {
static hasOne = [address:Address]
}

第二种方法是将外键移动到Address表,而不是person表。

这样做的实际好处(或缺点)是什么?据我所知,他们都会使用外键,只是外键住在哪里的问题。

如果地址表上存在外键,则该地址只能有一个人。如果外键在人员表上,则多个人员可以具有相同的地址。

这不是关于哪种方式更好/更糟。这是关于对数据建模的正确方法。

我发现在Grails中使用hasOne特别令人困惑。例如,这个问题询问当toOne关系声明如下时会发生什么:

class Person {
static hasOne = [address: Address]
}

如上所述,这会导致person_id外键出现在Address表中,这意味着每个Address只能指向一个人。我觉得奇怪的是,即使代码写为"一个人有一个地址",实际结果却是"一个地址有一个人"。

事实上,如上所述,没有任何东西(在数据库级别)阻止多个地址记录指向同一个人,这意味着一个人根本不必有一个地址。

有趣的是,如果你创建这样的Address类,你会得到相同的数据库表示:

class Address {
Person person
}

person_id外键将在Address表中,就像前面的例子一样,但很明显,如果不以某种方式定义关系,就无法从代码中的Person到Address。

同样有趣的是,如果您在数据库中建模从Person到Address的toMany关系,您将使用相同的表布局。您可以将父表的主键(person_id)放入子表中。从数据库的角度来看,使用hasOne可以创建与toMany关系相同的结构。

当然,我们不仅仅是在创建数据库表,我们还在创建Grails域类,这些类具有一些与之相关的行为,以及一些关系语义的强制执行。在这个特定的业务示例中,您可能不想与多个人共享同一个地址记录,只想单独存储地址(可能是为一个人有多个地址的那一天做准备)。我可能会投票支持这种方法:

class Person {
Address address
static constraints = {
address unique:true
}
}

address_id外键将在Person表中,并且唯一约束将强制没有两个Person记录指向同一地址。

我建议如下。。。

class Person {
...
static hasOne = [address: Address]
}
class Address {
...
static belongsTo = [person: Person]
}

一个人有一个地址,这个地址属于一个人。

这样,当你删除一个人时,地址也会被删除,不会有任何问题。

我认为这是更好的方法。

人员">hasOne">地址联系人

在"子"表上设置外键更有意义,因为这样,如果缺少父表,子表就会断开。个人可以在没有地址的情况下存在,但没有个人的"个人地址"是没有意义的。因此地址应该是关系中较弱的一方。

在grails中这样做,两个实体都会有彼此的引用,所以不会觉得奇怪。此外,当您保存人员时,默认级联行为将保存并删除地址,但如果您想删除AddressPerson将保持保存状态。

最新更新