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】:Person“hasOne”Address和Address“belongsTo” 人。
在“子”表上放置外键更有意义,因为这样如果父项丢失,子项就会中断。 Person 可以在没有地址的情况下存在,但没有人的“人的地址”是没有意义的。所以地址应该是关系中较弱的一面。
在 grails 中这样做,两个实体都会相互引用,所以不会觉得奇怪。此外,当您保存 Person 时,默认的级联行为将保存和删除 Address,但如果您想删除 Address,则 Person 将保持保存状态。
【讨论】:
以上是关于grails hasOne vs 直接成员变量的主要内容,如果未能解决你的问题,请参考以下文章
静态成员变量初始化在vs中报错“error LNK2005 static VimbaSystem...已经在...obj中定义”