作成しているデータモデルに対してどのようなアプローチを取るべきかを理解しようとしています。複合キーを使用して最初に作成した2つのテーブルがあります。ここで、前の2つの結合テーブルである3番目のテーブルを追加します。これにより、3つのフィールドの複合キーと、それぞれ2つのフィールドを持つ2つの外部キーが作成されます。これはMySQLにある可能性が高く、ある種のJava永続性フレームワークと一緒に使用されます。データを表現するためのより自然な方法のように思われるので、私は常に複合キーを使用するのが好きでしたが、後で傷ついた世界に身を置いていないことを確認したいと思います。上記のアプローチを続行する必要がありますか、それともテーブルに自動インクリメントIDを作成する必要がありますか?
3 に答える
Hibernateは、純粋に技術的な自動生成された非複合キー(純粋な結合テーブルを除く)を使用することをお勧めします。そして、非常に正当な理由で、IMO。
複合キーを使用すると、マッピングがはるかに難しくなります。インデックスがより複雑になるため、パフォーマンスが低下します。特定のエンティティをlongだけで識別できるのではなく、2つまたは3つのlongが必要になるため(たとえば、2つまたは3つのパラメータを入力する必要があるURLやフォームについて考えてみてください)、一般的なプログラミングは難しくなります。 / URL /フォームへの非表示フィールド)。
そしてもちろん、キーが機能している場合はさらに悪いことになります。主キーの一部を変更する必要があり、この主キーへのすべての参照を更新する必要があるためです。
多対多が純粋な関係(それ自体に属性がない)であり、それ自体が参照されることは決してない場合は、複合キーを使用するだけです。
それ自体が属性を持っているか、参照されている(クラスとしてインスタンス化されているなど)場合は、多くのが単一の整数であるORM
必要があるため、代理キーが必要になる場合があります。id
結合テーブルの代理キーには、外部キーとのより深い関係を制約する場合に大きな欠点があります。それを実証するには、6つのテーブルのセットアップが必要です。
ベーステーブル:
CREATE TABLE semester (semester_id INTEGER PRIMARY KEY, semester_name VARCHAR(40));
CREATE TABLE student (student_id INTEGER PRIMARY KEY, student_name VARCHAR(40));
CREATE TABLE subject (subject_id INTEGER PRIMARY KEY, subject_name VARCHAR(40));
次に、それらを接続しましょう。
CREATE TABLE enrollment (
enrollment_id INTEGER PRIMARY KEY,
semester_id INTEGER NOT NULL,
student_id INTEGER NOT NULL,
room_number INTEGER,
FOREIGN KEY (semester_id) REFERENCES semester (semester_id),
FOREIGN KEY (student_id) REFERENCES student (student_id),
UNIQUE INDEX (semester_id, student_id)
);
-- similarly ...
CREATE TABLE class(class_id ..., semester_id ..., subject_id ..., class_number ...);
これまでのところ、すべてが素晴らしいです。ただし、それらをもう少し接続する必要があります。
CREATE TABLE grades (
student_in_class_id INTEGER PRIMARY KEY,
enrollment_id INTEGER NOT NULL,
class_id INTEGER NOT NULL,
grade char(1),
FOREIGN KEY enrollment (enrollment_id),
FOREIGN KEY class (class_id),
UNIQUE INDEX (enrollment_id, class_id)
);
問題: 登録とクラスの両方が同じ学期を参照するように、いったいどのように強制することになっていますか?(簡単な答え:できません)
複合キーについても同じです。ここでは、外部キーに一意の組み合わせを適用するための追加のキーは必要ありません。主キーは、デフォルトでそれを実行します。
CREATE TABLE enrollment (
semester_id INTEGER NOT NULL,
student_id INTEGER NOT NULL,
room_number INTEGER,
PRIMARY KEY (semester_id, student_id),
FOREIGN KEY (semester_id) REFERENCES semester (semester_id),
FOREIGN KEY (student_id) REFERENCES student (student_id)
);
-- along the same lines...
class(semester_id ..., subject_id ..., class_number ...)
次に、不吉な成績表:
CREATE TABLE grades (
semester_id INTEGER NOT NULL,
student_id INTEGER NOT NULL,
subject_id INTEGER NOT NULL,
PRIMARY KEY (semester_id, student_id, subject_id),
FOREIGN KEY (semester_id, student_id) REFERENCES enrollment(semester_id, student_id),
FOREIGN KEY (semester_id, subject_id) REFERENCES class(semester_id, subject_id)
);
このようにして、私は自分の関係を適切に表現し、制約します。
追加のボーナス:(semester_name
複数のレベルを介してスキーマをトラバースする代わりに)単純な結合で値student_name
を取得できsubject_name
ます。この最も単純な例よりも多くのレベルがある可能性が高く、それからさらに簡単になります。親の関係のいずれかに戻ることです。
スキーマの変更はそれほど複雑ではありませんが、たとえそうであったとしても、データモデリングはモデリングデータに関するものではありませんか?代理キーが大好きだからといって、参照整合性を捨てることはできますか?
注: Hibernateは複合キーを処理します。DataMapperforRubyも同様です。