119 votes

Quelle est la différence entre inversedBy et mappedBy ?

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

En rédigeant des annotations, je ne parviens pas à comprendre la différence entre mappedBy y inversedBy .

Quand dois-je utiliser mappedBy ?

Quand dois-je utiliser inversedBy ?

Quand dois-je utiliser ni l'un ni l'autre ?

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 j'ai trouvé ce qui suit, mais je ne comprends toujours pas :

178voto

Andreas Linden Points 6344
  • mappedBy doit être spécifié sur le côté inversé d'une association (bidirectionnelle)
  • inverséPar doit être spécifié sur le côté propriétaire d'une association (bidirectionnelle)

de la documentation sur la doctrine :

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

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

72voto

Joseph Astrahan Points 254

Les réponses ci-dessus n'étaient pas suffisantes pour que je comprenne ce qui se passait, alors après avoir approfondi le sujet, je pense avoir trouvé une façon de l'expliquer qui aura du sens pour les personnes qui ont eu du mal comme moi à comprendre.

inversedBy et mappedBy sont utilisés par la fonction DOCTRINE INTERNE moteur pour réduire le nombre de requêtes SQL qu'il doit faire 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 exécutez 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 comporte pas de colonne pour les tâches. (c'est parce qu'il n'y a pas d'annotation de colonne).

Ce qu'il est important de comprendre ici, c'est que la variable tasks n'est là que pour que le moteur de doctrine interne puisse utiliser la référence qui se trouve au-dessus et qui indique que la variable mappedBy Category. Maintenant... ne soyez pas confus comme je l'ai été... La catégorie ne fait PAS référence au nom de la classe il se réfère à la propriété de la classe Task appelée "protected $category".

De même, sur la classe Tasks, la propriété $category mentionne qu'elle est inversedBy="tasks", remarquez que c'est au pluriel, ce n'est PAS LE PLURIEL DU NOM DE LA CLASSE mais simplement parce que la propriété est appelée "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 fait référence à la clé étrangère, comme 'tasks' dans mon exemple, obtient toujours l'attribut inversedBy parce qu'il doit savoir quelle classe (via la commande targetEntity) et quelle variable (inversedBy=) sur cette classe pour 'travailler en arrière', pour ainsi dire, et obtenir les informations sur la catégorie. Une façon simple de s'en souvenir est de dire que la classe qui aurait la foreignkey_id est celle qui doit avoir inversedBy.

Comme pour la catégorie, et sa propriété $tasks (qui n'est pas sur la table, rappelez-vous, mais seulement une partie de la classe à des fins d'optimisation) est MappedBy 'tasks', cela crée officiellement la relation entre les deux entités de sorte que doctrine peut maintenant utiliser en toute sécurité des instructions SQL JOIN au lieu de deux instructions SELECT séparées. Sans mappedBy, le moteur de doctrine ne saurait pas, à partir de l'instruction JOIN, quelle variable de la classe 'Task' il doit créer pour y placer les informations relatives à la catégorie.

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

23voto

ahmed hamdy Points 1020

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

mappedBy : mettre en Le côté inverse d'une relation bidirectionnelle Se référer à son côté propriétaire

inverséPar : mettre en Le côté propriétaire d'une relation bidirectionnelle Se référer à son côté inverse

ET

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

inverséPar utilisé avec la déclaration de mappage OneToOne, ManyToOne ou ManyToMany.

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

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

2voto

5.9.1. Propriété et revers

Pour les associations Many-To-Many, vous pouvez choisir quelle entité est le propriétaire et quelle entité est l'inverse. Il existe une règle sémantique très simple pour décider quel côté est le plus approprié pour être le côté propriétaire du point de vue des développeurs. Il suffit de se demander quelle entité est responsable de la gestion des connexions et de la choisir comme côté propriétaire.

Prenons l'exemple de deux entités : Article et Tag. Lorsque vous souhaitez connecter un article à une étiquette et vice-versa, c'est généralement l'article qui est responsable de cette relation. Lorsque vous ajoutez un nouvel article, vous voulez le relier à des étiquettes existantes ou nouvelles. Votre formulaire de création d'article prendra probablement en charge cette notion et permettra de spécifier les étiquettes directement. C'est pourquoi vous devriez choisir l'article comme propriétaire, car cela rend le code plus compréhensible :

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X