23

私が次のようなgrailsドメインクラスを持っているとしましょう

class Person {
    Address address
}

私はそれを次のように宣言することもできます

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

2番目の方法では、外部キーをpersonテーブルではなくAddressテーブルに移動します。

これを一方の方法ともう一方の方法で行うことの実際的なメリット(またはデメリット)は何ですか?私が理解している限り、どちらも外部キーを使用します。外部キーがどこにあるかだけが問題です。

4

4 に答える 4

30

外部キーがアドレステーブルに存在する場合、そのアドレスは1人しか持つことができません。外部キーが個人テーブルにある場合、複数の個人が同じアドレスを持つことができます。

それは、どのように良い/悪いかではありません。それはあなたのデータをモデル化する正しい方法が何であるかについてです。

于 2012-10-15T17:09:04.430 に答える
25

hasOneGrailsでの使用は特に紛らわしいと思います。たとえば、この質問では、toOne関係が次のように宣言されたときに何が起こるかを尋ねます。

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

上記のように、これによりperson_id外部キーがアドレステーブルに表示されます。つまり、各アドレスは1人の個人のみを指すことができます。奇妙なことに、コードは「1人の住所が1人」と書かれていても、実際の結果は「1人の住所が1人」ということです。

実際、上記のように定義されているだけで、(データベースレベルで)複数のAddressレコードが同じPersonを指すことを妨げるものはありません。つまり、Personが実際に1つのAddressを持つ必要はありません。

興味深いことに、次のようにAddressクラスを作成した場合、同じデータベース表現が得られます。

class Address {
    Person person
}

前のperson_id例と同じように、外部キーはAddressテーブルにありますが、明らかに、何らかの方法でその関係を定義しない限り、コード内のPersonからAddressに到達することはできません。

また、データベース内の個人から住所へのtoMany関係をモデル化する場合は、同じテーブルレイアウトを使用することも興味深いことです。親の主キー(person_id)を子テーブルに配置します。データベースの観点からすると、を使用hasOneすると、toMany関係が作成するのと同じ構造が作成されます。

もちろん、データベーステーブルを作成するだけでなく、いくつかの動作が関連付けられたGrailsドメインクラスを作成し、関係セマンティクスを強制します。この特定のビジネス例では、同じ住所レコードを複数の人と共有するのではなく、住所を個別に保存するだけです(人が複数の住所を持っている日の準備をする場合もあります)。私はおそらくこのアプローチに投票するでしょう:

class Person {
    Address address

    static constraints = {
        address unique:true
    }
}

外部キーはaddress_idPersonテーブルにあり、一意の制約により、2つのPersonレコードが同じアドレスを指していることはありません。

于 2013-04-22T19:34:06.253 に答える
9

私は次のことを提案します...

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

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

人は1つのアドレスを持ち、そのアドレスは1人の人に属します。

このように、人を削除すると、住所も問題なく削除されます。

これがこれを行うためのより良い方法だと思います。

于 2014-01-31T20:39:56.550 に答える
7

Person " hasOne " Address and the Address " belongsTo " thePerson

「子」テーブルに外部キーがあると、親が見つからない場合に子が壊れてしまうため、より理にかなっています。はその住所がなくても存在できますが、人がいない「人の住所」は意味がありません。したがって、アドレスは関係の弱い側である必要があります。

グレイルでこのように行うと、両方のエンティティが相互に参照するため、奇妙に感じることはありません。また、デフォルトのカスケード動作では、個人を保存するときにアドレスが保存および削除されますが、アドレスを削除する場合は、個人は保存されたままになります。

于 2014-04-14T15:18:12.683 に答える