11

私は現在、次のようなモデル構造を持っています。

/**
 * @ORM\Entity
 * @ORM\InheritanceType("JOINED")
 * @ORM\DiscriminatorColumn(name="related_type", type="string")
 * @ORM\DiscriminatorMap({"type_one"="TypeOne", "type_two"="TypeTwo"})
 */
abstract class BaseEntity {

    ... (all the usual stuff, IDs, etc)

    /**
     * @ORM\OneToMany(targetEntity="Comment", mappedBy="baseEntity")
     */
    private $comments;
}

/**
 * @ORM\Entity
 */
class TypeOne extends BaseEntity {
    /**
     * @ORM\Column(type="string")
     */
    private $name;

    /**
     * @ORM\Column(type="string")
     */
    private $description;
}

/**
 * @ORM\Entity
 */
class TypeTwo extends BaseEntity {
    /**
     * @ORM\Column(type="string")
     */
    private $name;

    /**
     * @ORM\Column(type="string")
     */
    private $description;   
}

/**
 * @ORM\Entity
 */
class Comment {

    ... (all the usual stuff, IDs, etc)

    /**
     * @ORM\ManyToOne(targetEntity="BaseEntity", inversedBy="comments")
     */
    private $baseEntity;
}

ここでの考え方は、コメントを他のテーブルのいずれかに結び付けることができるようにすることです。これは今のところすべて正常に機能しているようです(もちろん、私はまだ設計オプションを検討しているので、これを行うためのより良い方法があるかもしれません...)が、私が気付いた1つのことは、サブクラスにいくつかの共通フィールドがあることです共通の親クラスに移動したいと思います。BaseEntityの子である他のオブジェクトがあるので、それらをBaseEntityに移動したくありませんが、それらのフィールドはありません。

次のように、途中でMappedSuperclass親クラスを作成することを検討しました。

/**
 * @ORM\MappedSuperclass
 */
abstract class Common extends BaseEntity {
    /**
     * @ORM\Column(type="string")
     */
    private $name;

    /**
     * @ORM\Column(type="string")
     */
    private $description;       
}

/**
 * @ORM\Entity
 */
class TypeOne extends Common {}

/**
 * @ORM\Entity
 */
class TypeTwo extends Common {}

これでうまくいくと思いましたが、Doctrineデータベーススキーマジェネレーターは、MappedSuperclassにOneToManyマッピングを設定できないと不平を言っています。OneToManyマッピングはまだルートBaseEntityとCommentテーブルの間にあるため、これが問題になるとは思っていませんでした。BaseEntityに追加せずにこれらのフィールドを共通にするために使用する必要がある別の構造、または他の方法はありますか?

4

1 に答える 1

14

ドキュメントから:

マップされたスーパークラスは、そのサブクラスの永続的なエンティティ状態とマッピング情報を提供する抽象クラスまたは具象クラスですが、 それ自体はエンティティではありません。通常、このようなマップされたスーパークラスの目的は、複数のエンティティクラスに共通する状態およびマッピング情報を定義することです。

そうは言っても、あるエンティティをそうでないエンティティにどのように関連付けることができますか?

ドキュメントからのより多く:

マップされたスーパークラスをエンティティにすることはできません。クエリ可能ではなく、マップされたスーパークラスによって定義される永続的な関係は単方向である必要があります(所有側のみ)。これは、マップされたスーパークラスでは1対多の関連付けがまったくできないことを意味します。 さらに、多対多の関連付けは、マップされたスーパークラスが現時点で1つのエンティティでのみ使用されている場合にのみ可能です。継承をさらにサポートするには、単一テーブル継承機能または結合テーブル継承機能を使用する必要があります。

ソース:http ://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/inheritance-mapping.html


アップデート

MappedSuperClassはBaseEntityを拡張するため、BaseEntityの関連付けも、それ自体であるかのように継承します。したがって、事実上、MappedSuperClassにOneToManyがあります。

それを回避するには、あなたが望むように機能するように教義を修正/拡張する必要があります。

ネイティブ機能に関する限り、2つのオプションがあります。

クラステーブル継承YouCommon クラスと結果のDB表現には共通フィールドがあり、子クラスにはそれ自体に固有のフィールドのみが含まれるようになります。残念ながら、単に共通のフィールドをグループ化するためにグループ化しようとしている場合、これはデータの不実表示である可能性があります。

共通をエンティティ にするマップされたスーパークラスはすべて、DBに表示されていないエンティティであるように見えます。したがって、代わりにエンティティを共通にします。欠点は、最終的にDBテーブルが作成されることですが、それを削除することもできます。

データをもう一度確認し、名前と目的の両方で共通している場合にのみフィールドをグループ化することを確認することをお勧めします。たとえば、ComputerBox、ShoeBox、Man、Womanはすべて「height」プロパティを持っているかもしれませんが、その場合、それらすべてが継承する「height」プロパティを持つCommonクラスを持つことはお勧めしません。代わりに、ComputerBoxとShoeBoxに共通のフィールドを持つBoxがあり、ManとWomanに共通のフィールドを持つPersonがあります。そのような状況では、クラステーブル継承または単一テーブルが完全に機能します。

データがその例に従っている場合は、単一テーブルまたはクラステーブル継承を使用します。そうでない場合は、フィールドをグループ化しないことをお勧めします。

于 2012-09-05T18:38:25.077 に答える