web-dev-qa-db-fra.com

Quelle est la difference entre inversedBy et mappedBy?

Je développe mon application avec Zend Framework 2 et Doctrine 2.

En écrivant des annotations, je suis incapable de comprendre la différence entre mappedBy et inversedBy.

Quand devrais-je utiliser mappedBy?

Quand devrais-je utiliser inversedBy?

Quand devrais-je utiliser ni?

Voici un exemple:

 /**
 *
 * @ORM\OneToOne(targetEntity="\custMod\Entity\Person", mappedBy="customer")
 * @ORM\JoinColumn(name="personID", referencedColumnName="id")
 */
protected $person;

/**
 *
 * @ORM\OneToOne(targetEntity="\Auth\Entity\User")
 * @ORM\JoinColumn(name="userID", referencedColumnName="id")
 */
protected $user;

/**
 *
 * @ORM\ManyToOne (targetEntity="\custMod\Entity\Company", inversedBy="customer")
 * @ORM\JoinColumn (name="companyID", referencedColumnName="id")
 */
protected $company;

J'ai fait une recherche rapide et trouvé ce qui suit, mais je suis toujours confus:

96
Developer
  • mappéPar doit être spécifié du côté côté inversé d'une association (bidirectionnelle)
  • inversedBy doit être spécifié du côté propriétaire d'une association (bidirectionnelle)

de doctrine documentation:

  • ManyToOne est toujours le côté propriétaire d'une association bidirectionnelle.
  • OneToMany est toujours le côté inverse d'une assocation bidirectionnelle.
  • Le côté propriétaire d'une association OneToOne est l'entité avec la table contenant la clé étrangère.

Voir https://www.doctrine-project.org/projects/doctrine-orm/en/latest/reference/unitofwork-associations.html

151
Andreas Linden

Les réponses ci-dessus n'étaient pas suffisantes pour que je comprenne ce qui se passait, donc après avoir approfondi le sujet, je pense avoir un moyen de l'expliquer qui aura du sens pour les personnes qui ont eu du mal à comprendre.

inversedBy et mappedBy sont utilisés par le moteur INTERNAL DOCTRINE pour réduire le nombre de requêtes SQL nécessaire pour obtenir les informations dont vous avez besoin. Pour être clair si vous n’ajoutez pas inversedBy ou mappedBy, votre code fonctionnera toujours mais ne sera pas optimisé.

Ainsi, par exemple, regardez les classes ci-dessous:

class Task
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="task", type="string", length=255)
     */
    private $task;

    /**
     * @var \DateTime
     *
     * @ORM\Column(name="dueDate", type="datetime")
     */
    private $dueDate;

    /**
     * @ORM\ManyToOne(targetEntity="Category", inversedBy="tasks", cascade={"persist"})
     * @ORM\JoinColumn(name="category_id", referencedColumnName="id")
     */
    protected $category;
}

class Category
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="name", type="string", length=255)
     */
    private $name;

    /**
     * @ORM\OneToMany(targetEntity="Task", mappedBy="category")
     */
    protected $tasks;
}

Ces classes si vous deviez exécuter la commande pour générer le schéma (par exemple, bin/console doctrine:schema:update --force --dump-sql) vous remarquerez que la table Catégorie ne contient pas de colonne pour les tâches. (c'est parce qu'il n'y a pas d'annotation de colonne dessus)

La chose importante à comprendre ici est que la variable tâches est seulement là pour que le moteur interne doctrine puisse utiliser la référence au-dessus de celle-ci qui dit sa catégorie mappedBy. Maintenant ... ne vous y trompez pas comme si j'étais ... La catégorie ne fait PAS référence au nom de la classe, elle fait référence à la propriété de la classe de tâches appelée "catégorie de protection".

De même, dans la classe Tasks, la propriété $ category mentionne qu'elle est inverséePar = "tâches", notez que ceci est un pluriel, ce n'est pas la pluralité du nom de la classe, mais simplement parce que la propriété s'appelle ' protected $ tasks 'dans la classe Category.

Une fois que vous avez compris cela, il devient très facile de comprendre ce que font inversedBy et mappedBy et comment les utiliser dans cette situation.

Le côté qui référence la clé étrangère comme "tâches" dans mon exemple obtient toujours l'attribut inversedBy car il a besoin de savoir quelle classe (via la commande targetEntity) et quelle variable (inversedBy =) sur cette classe pour "travailler à l'envers" parler et obtenir les informations de catégorie de. Un moyen simple de s'en souvenir est que la classe qui aurait le code foreignkey_id est celle qui doit être inversée par.

Où, comme avec category, et sa propriété $ tasks (qui ne figure pas dans la table, rappelez-vous, mais seulement une partie de la classe à des fins d'optimisation) est MappedBy, cela crée officiellement la relation entre les deux entités de sorte que doctrine peut désormais utiliser en toute sécurité les instructions JOIN SQL au lieu de deux instructions SELECT distinctes. Sans mappedBy, le moteur doctrine ne saurait pas, à partir de l'instruction JOIN, il créera quelle variable dans la classe. 'Task' pour mettre les informations de catégorie.

J'espère que cela l'explique un peu mieux.

52
Joseph Astrahan

Dans une relation bidirectionnelle, il existe à la fois un côté propriétaire et un côté inverse

mappedBy : placé dans le côté inverse d'une relation bidirectionnelle Pour faire référence à son propre côté

inversedBy : mettre dans le côté propriétaire d'une relation bidirectionnelle Pour faire référence à son côté inverse

[~ # ~] et [~ # ~]

mappedBy attribut utilisé avec la déclaration de mappage OneToOne, OneToMany ou ManyToMany.

inversedBy attribut utilisé avec la déclaration de mappage OneToOne, ManyToOne ou ManyToMany.

Remarque : Le côté propriétaire d'une relation bidirectionnelle est le côté qui contient la clé étrangère.

il existe deux références sur inversedBy et mappedBy dans Doctrine Documentation: Premier lien , Deuxième lien

20
ahmed hamdy

5.9.1. Posséder et inverser

Pour les associations plusieurs-à-plusieurs, vous pouvez choisir quelle entité appartient et laquelle est inversée. Il existe une règle sémantique très simple pour décider quel côté est le plus approprié pour être le propriétaire du point de vue des développeurs. Il vous suffit de vous demander quelle entité est responsable de la gestion de la connexion et de choisir celle qui en est le propriétaire.

Prenons un exemple de deux entités Article et Tag. Chaque fois que vous souhaitez connecter un article à une étiquette et inversement, c'est principalement l'article qui est responsable de cette relation. Chaque fois que vous ajoutez un nouvel article, vous souhaitez le connecter à des balises existantes ou nouvelles. Votre formulaire de création d'article supportera probablement cette notion et permettra de spécifier directement les balises. C’est pourquoi vous devriez choisir l’article comme côté propriétaire, car cela rend le code plus compréhensible:

http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/association-mapping.html