1

私は関係であるエンティティを持つ大規模なデータベースを持っています。これはまさにDoctrine 2 マニュアルの次のコメントによるものです: 私はリレーションに追加の属性を保存する必要があり、このためリレーションはエンティティになりました。

通常、エンティティには生成された ID を使用し、関係には複合キーを使用します。この場合、エンティティは関係であるため、選択が少し複雑になります...

ここでは自然キーについて話しているわけではないことに注意してください。それぞれの所有エンティティで自動インクリメント戦略を使用して作成された整数である ID から構成される複合キーを使用しています。

リレーションシップ エンティティで複合主キーを使用することには、いくつかの欠点があります。

  • エンティティとその関係を作成する間に persist を呼び出す必要があります (複合主キーで外部キーとして使用する前に、エンティティでキーを生成するため)。
  • 追加のエンティティを関係エンティティに関連付けるには、複合キーで使用される ID の列をそれらのエンティティに再度追加する必要があります。サロゲート主キーを使用する場合、その 1 つの ID を保持する 1 つの列だけが必要です。

たとえば、複合キーを使用する利点もいくつかあります。

  • 特定の結合クエリが不要になる代わりに、複合キーを使用して情報を直接抽出するクエリを作成できます。

しかし、現時点で複合キーを使用するための最も重要な議論は次のとおりです。

  • User と SomeEntity の間の関係が削除され、後で再び作成された場合 (アプリケーション モデルで発生する可能性が高いシナリオ)、他のすべての関連エンティティへのアクセスも復元する必要があります。User と SomeEntity の間の関係が、代理主キーの自動インクリメント戦略を使用して作成されている場合。復元された (新しい) 関係は、新しい主キー (id) を取得します。このため、関連するエンティティ (「古い」キーを使用して格納されている) にはアクセスできなくなります。リレーションシップで複合キーを使用すると、単純にリレーションシップを復元でき (同じ複合キー値を取得します)、それによって、他の関連するエンティティにすぐにアクセスできるようになります。

同様のシナリオを経験した人はいますか? これを適切に機能させるための他の解決策はありますか。私が見逃した重要な欠点や利点 (Doctrine ORM を使用する場合) はありますか?

私が考えることができる 1 つの代替手段は、状態を User SomeEntity 関係に追加することです。エントリを削除する代わりに、状態を無効、有効に変更できます。そのようにして、エントリが削除されないため、複合キーの代わりに代理キーを使用できます...

フィードバックは大歓迎です...

興味のある人のために、スタックオーバーフローのサロゲートキーと複合キーに関する素晴らしい議論もありました: (クリック)

4

1 に答える 1

1

2 つの外部キーを複合主キーにすることを提案します。

関連エンティティは、その 2 つの関係の ID によって識別されます。

理論的には、Doctrine の UnitOfWork/CommitOrderCalculator は要素を正しい順序で挿入する必要があるため、永続的な順序を扱う必要はありません。

マッピングは最後に次のようになります (注釈の例):

<?php

class UserGroup
{
    /**
      * @ORM\ManyToOne(targetEntity="User")
      * @ORM\Id
     **/
    public $user;

    /**
      * @ORM\ManyToOne(targetEntity="Group")
      * @ORM\Id
     **/
    public $group;
}
于 2013-05-17T14:32:04.840 に答える