我发现在 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 记录指向同一个地址。