Mapping de l'héritage Symfony2


Table des matières

Référence
Mapped Superclasses
Héritage d'une seule table
Les considérations "Design-time"
Impact sur ​​les performances
Considérations Schéma SQL
Héritage de Table classe
Au moment du design considérations
Impact sur ​​les performances
Considérations Schéma SQL

Référence

http://www.doctrine-project.org/docs/orm/2.1/en/reference/inheritance-mapping.html

Mapped Superclasses

Une "Mapped Superclasses" est une classe abstraite ou concrète qui fournit l'état d'une entité persistante et ''information pour la cartographie de ses sous-classes, mais qui n'est pas en soi une entité. Typiquement, le but d'un tel superclasse mappée est de définir les informations d'état et de la cartographie qui est commun à plusieurs classes d'entités.

Une "Mapped Superclasses", tout aussi correct, peut apparaître au milieu d'une hiérarchie d'héritage mappée différemment (par héritage ou d'héritage à table unique tableau de classe).

Une "Mapped Superclasses" ne peut pas être une entité, il n'est pas en mesure d'effectuer des requêtes et des relations définies par la persistance d'une superclasse.Il est unidirectionnel. Cela signifie qu'une association One-To-Many n'est pas possibles sur une "Mapped Superclasses" à tous. En outre, beaucoup-à-plusieurs ne sont possibles que si la "Mapped Superclasses" n'est utilisé que dans une seule entité pour le moment. Pour un support supplémentaire de l'héritage, les relations directes ou les jointures d'héritage de table doivent être utilisés.

Exemple:

</s<?php
/** @MappedSuperclass */
class MappedSuperclassBase
{
    /** @Column(type="integer") */
    protected $mapped1;
    /** @Column(type="string") */
    protected $mapped2;
    /**
     * @OneToOne(targetEntity="MappedSuperclassRelated1")
     * @JoinColumn(name="related1_id", referencedColumnName="id")
     */
    protected $mappedRelated1;

    // ... more fields and methods
}

/** @Entity */
class EntitySubClass extends MappedSuperclassBase
{
    /** @Id @Column(type="integer") */
    private $id;
    /** @Column(type="string") */
    private $name;

    // ... more fields and methods
}

Le DDL pour le schéma de la base correspondante devrait ressembler à ceci (ce n'est pour SQLite):

CREATE TABLE EntitySubClass (mapped1 INTEGER NOT NULL, mapped2 TEXT NOT NULL, id INTEGER NOT NULL, name TEXT NOT NULL, related1_id INTEGER DEFAULT NULL, PRIMARY KEY(id))

Comme vous pouvez le voir sur cet extrait DDL, il y a seulement une table unique pour la sous-classe entité. Tous les mappages de la "mapped superclass" ont été hérités de la sous-classe comme si elles avaient été définis pour cette classe directement.

Héritage d'une seule table

L'héritage d'une seule table est une stratégie de mapping d'héritage où toutes les classes d'une hiérarchie sont mappées à une table de base de données unique. Afin de distinguer ce qui rangée représente le type dans la hiérarchie une colonne discriminante est utilisée.

Exemple:

<?php
namespace MyProject\Model;

/**
 * @Entity
 * @InheritanceType("SINGLE_TABLE")
 * @DiscriminatorColumn(name="discr", type="string")
 * @DiscriminatorMap({"person" = "Person", "employee" = "Employee"})
 */
class Person
{
    // ...
}

/**
 * @Entity
 */
class Employee extends Person
{
    // ...
}

Points à noter:

Les considérations "Design-time"

Cette approche de cartographie fonctionne bien lorsque la hiérarchie des types est assez simple et stable. Ajout d'un nouveau type à la hiérarchie et l'ajout de champs à supertypes existante implique simplement d'ajouter de nouvelles colonnes à la table, bien que dans les grands déploiements cela peut avoir un impact négatif sur l'indice et l'agencement intérieur de la colonne de base de données.

Impact sur ​​les performances

Cette stratégie est très efficace pour l'interrogation dans tous les types de la hiérarchie ou pour des types spécifiques. Pas de jointures de tables sont nécessaires, seule une clause WHERE énumérant les identificateurs de type. En particulier, les relations impliquant des types qui emploient cette stratégie de mapping sont très performantes.

Il y a une considération de performances générales avec l'héritage de table simple: Si la "target-entity" d'une association many-to-one ou d'un one-to-one est une entité STI, il est préférable pour des raisons de performances que ce soit une entité feuille dans l'héritage hiérarchie, (ie. n'ont pas les sous-classes). Sinon doctrine ne peut pas créer des instances de procuration de cette entité et sera toujours chargé de l'entité.

Considérations Schéma SQL

Pour une table unique d'héritage à travailler dans les scénarios où vous utilisez soit un schéma de base de legs ou un schéma de base auto-écrit, vous avez à faire en sorte que toutes les colonnes qui ne sont pas dans l'entité racine et dans aucunes des différents sous-entités doivent autoriser les valeurs NULL. Les colonnes qui ont NOT NULL doivent être sur l'entité racine de la hiérarchie d'héritage à table unique.

Héritage de Table classe

La classe d'une table d'héritage est une stratégie de mapping d'héritage où chaque classe dans une hiérarchie est mappé à plusieurs tables: sa propre table et les tables de toutes les classes parentes. Le tableau d'une classe de l'enfant est liée à la table d'une classe parent grâce à une contrainte de clé étrangère. Doctrine2 implémente cette stratégie à travers l'utilisation d'une colonne discriminante dans la table le plus élevé de la hiérarchie parce que c'est la meilleure façon d'atteindre des requêtes polymorphiques l'héritage de table de classe.

Exemple:

<?php
namespace MyProject\Model;

/**
 * @Entity
 * @InheritanceType("JOINED")
 * @DiscriminatorColumn(name="discr", type="string")
 * @DiscriminatorMap({"person" = "Person", "employee" = "Employee"})
 */
class Person
{
    // ...
}

/** @Entity */
class Employee extends Person
{
    // ...
}

Points à noter:

Lorsque vous n'utilisez pas le SchemaTool pour générer le code SQL nécessaire que vous devriez savoir que la suppression d'un héritage de table de classe rend l'utilisation de la propriété de clé étrangère ON DELETE CASCADE dans toutes les implémentations de bases de données. Un échec à mettre en œuvre vous-même conduira à lignes mortes dans la base de données.

Au moment du design considérations

L'introduction d'un nouveau type à la hiérarchie, à tout niveau, implique simplement interposant une nouvelle table dans le schéma. Les sous-types de ce type sera automatiquement se joindre à ce nouveau type à l'exécution. De même, la modification de toute type d'entité dans la hiérarchie en ajoutant, modifiant ou supprimant des champs ne concerne que la table mappée immédiate de ce type. Cette stratégie de cartographie fournit la plus grande flexibilité au moment du design, puisque les changements à tout type sont toujours limitées à table dédiée de ce type.

Impact sur ​​les performances

Cette stratégie nécessite intrinsèquement multiples opérations JOIN pour exécuter n'importe quel requête qui peut avoir un impact négatif sur les performances, surtout avec de grandes tables et / ou grandes hiérarchies. Lorsque les objets partiels sont autorisés, que ce soit globalement ou sur la requête spécifique, alors pour tout type d'interrogation ne sera pas provoquer les tableaux des sous-types à OUTER jointes qui peut augmenter les performances, mais les objets résultant partielle ne sera pas pleinement eux-mêmes la charge sur l'accès de tous les champs sous-type , donc l'accès aux champs des sous-types, après une telle requête n'est pas sûr.

Il y a une considération les performances générales avec l'Héritage de Table Classe: Si la cible-entité d'un nombre-to-one ou one-to-une association est une entité ICT, il est préférable pour des raisons de performances que ce soit une entité de feuilles dans l'héritage hiérarchie, (ie. n'ont pas les sous-classes). Sinon doctrine ne peut pas créer des instances de procuration de cette entité et sera toujours la charge de l'entité avec impatience.

Considérations Schéma SQL

Pour chaque entité dans la hiérarchie d'héritage de classe tableau tous les champs doivent être cartographiées colonnes sur la table de cette entité. En outre, chaque table enfant doit avoir une colonne id qui correspond à la définition de la colonne id sur la table racine (sauf pour une séquence ou d'auto-incrémentation de détails). En outre, chaque table enfant doit avoir une clé étrangère pointant de la colonne id de la colonne id racine de table et en cascade sur les supprimer.