grails hasOne vs 直接成员变量

Posted

技术标签:

【中文标题】grails hasOne vs 直接成员变量【英文标题】:grails hasOne vs direct member variable 【发布时间】:2012-10-05 16:45:35 【问题描述】:

假设我有一个看起来像这样的 grails 域类

class Person 
    Address address

我也可以声明为

class Person 
  static hasOne = [address:Address]

第二种方法是将外键移动到地址表而不是人员表。

采用这种方式与另一种方式相比有哪些实际好处(或缺点)?据我了解,它们都将使用外键,这只是外键所在位置的问题。

【问题讨论】:

【参考方案1】:

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

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

【讨论】:

有道理,谢谢。对不起,我在这里放了一点脑袋。我被 grails 机制所包围,并没有退后一步从数据库的角度考虑它。【参考方案2】:

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

class Person 
  static hasOne = [address: Address]

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

事实上,仅如上定义,没有什么(在数据库级别)阻止多个地址记录指向同一个人,这意味着一个人实际上不必有一个地址。

有趣的是,如果您像这样创建 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 记录指向同一个地址。

【讨论】:

hasOne 似乎对性能有影响(至少在我坚持的 2.2.0 中)。我正在分析并发现该关联被延迟加载,即使我没有使用它,导致大量不必要的数据库访问。将其切换为成员变量似乎已经消除了这一点。【参考方案3】:

我建议以下...

class Person 
  ...
  static hasOne = [address: Address]


class Address 
    ...
    static belongsTo = [person: Person]

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

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

我认为这是更好的方法。

【讨论】:

虽然房子通常不会在你死后被删除:D【参考方案4】:

PersonhasOneAddressAddressbelongsTo

在“子”表上放置外键更有意义,因为这样如果父项丢失,子项就会中断。 Person 可以在没有地址的情况下存在,但没有人的“人的地址”是没有意义的。所以地址应该是关系中较弱的一面。

在 grails 中这样做,两个实体都会相互引用,所以不会觉得奇怪。此外,当您保存 Person 时,默认的级联行为将保存和删除 Address,但如果您想删除 Address,则 Person 将保持保存状态。

【讨论】:

以上是关于grails hasOne vs 直接成员变量的主要内容,如果未能解决你的问题,请参考以下文章

Grails GORM 组合还是 hasOne?

unique_ptr vs 类实例作为成员变量

c++ 初始化列表VS构造函数内赋值初始化成员变量

c++ 初始化列表VS构造函数内赋值初始化成员变量

c++ 初始化列表VS构造函数内赋值初始化成员变量

静态成员变量初始化在vs中报错“error LNK2005 static VimbaSystem...已经在...obj中定义”