Quelle est la différence entre inversedBy et mappedBy?

je suis le développement de mon application à l'aide de Zend Framework 2 et Doctrine 2.

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

Quand dois-je utiliser mappedBy ?

Quand dois-je utiliser inversedBy ?

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

voici un exemple:

 /**
 *
 * @ORMOneToOne(targetEntity="custModEntityPerson", mappedBy="customer")
 * @ORMJoinColumn(name="personID", referencedColumnName="id")
 */
protected $person;

/**
 *
 * @ORMOneToOne(targetEntity="AuthEntityUser")
 * @ORMJoinColumn(name="userID", referencedColumnName="id")
 */
protected $user;

/**
 *
 * @ORMManyToOne (targetEntity="custModEntityCompany", inversedBy="customer")
 * @ORMJoinColumn (name="companyID", referencedColumnName="id")
 */
protected $company;

j'ai fait recherche rapide et trouvé le suivant, mais je suis encore confus:

  • exemple 1
  • exemple 2
  • exemple 3
86
demandé sur Community 2012-09-19 15:33:01

4 réponses

  • 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 doctrine de la documentation:

  • ManyToOne est toujours le propriétaire de côté d'une bidirectionnel l'assocation.
  • OneToMany est toujours le côté inverse d'une assocation bidirectionnelle.
  • le côté propriétaire d'une assocation 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

136
répondu Andreas Linden 2018-04-16 18:38:03

les réponses ci-dessus n'étaient pas suffisantes pour que je comprenne ce qui se passait, donc après y avoir réfléchi, je pense que j'ai une façon de l'expliquer qui aura du sens pour les gens qui ont lutté comme je l'ai fait pour comprendre.

inversedBy et mappedBy sont utilisés par le DOCTRINE interne moteur à réduire le nombre de requêtes SQL 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 Catégorie de la table n'a pas de colonne pour les tâches. (c'est parce qu'il n'a pas une colonne d'annotation)

l'important pour comprendre ici est que les tâches variables est seulement là afin que le moteur de doctrine interne peut utiliser la référence ci-dessus qui dit sa catégorie mappedBy. Maintenant... ne soyez pas confus ici comme je l'étais... La catégorie ne se réfère pas au nom de classe , mais à la propriété de la classe de tâches appelée "protected $category".

comme wise, sur la classe des tâches la propriété $category mentionne qu'elle est inversée par = "tâches", notez que c'est le pluriel, ce N'est pas le pluriel du nom de classe , mais juste parce que la propriété est appelée 'protected $tasks' dans la classe de catégorie.

une fois que vous comprenez 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 a besoin de savoir quelle classe (via la targetEntity commande) et quelle variable (inversedBy=) sur cette classe pour "travailler en arrière" pour ainsi dire et obtenir les informations de la catégorie. Un moyen facile de se souvenir de ceci, est la classe qui aurait le foreignkey_id est celle qui a besoin d'être inversée.

où comme avec la catégorie, et sa propriété $tasks (qui n'est pas sur la table rappelez-vous, juste une partie de la classe pour des fins d'optimisation) est MappedBy 'tasks', cela crée la relation officielle entre les deux des entités de sorte que la doctrine puisse maintenant utiliser en toute sécurité des instructions JOIN SQL au lieu de deux instructions SELECT séparées. Sans mappedBy, le moteur de doctrine ne saurait pas de L'énoncé JOIN qu'il créera quelle variable dans la classe "tâche" de mettre l'information de catégorie.

espérons que cela explique un peu mieux.

44
répondu Joseph Astrahan 2016-01-04 00:55:08

dans la relation bidirectionnelle a à la fois un côté propriétaire et un côté inverse

mappedBy : mis dans l'inverse d'une relation bidirectionnelle pour se référer à son côté propriétaire

inversé par : mis dans le côté propriétaire d'une relation bidirectionnelle pour se référer à son côté inverse

et

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

inversé par attribut utilisé avec la déclaration cartographique 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 à inversedBy et mappedBy dans la Documentation de Doctrine : Premier Lien , Second Lien

20
répondu ahmed hamdy 2013-11-20 16:12:38

5.9.1. Propriétaire et côté Inverse

pour plusieurs associations, vous pouvez choisir l'entité qui est propriétaire et l'inverse. Il y a 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. Vous n'avez qu'à vous demander quelle entité est responsable de la gestion de la connexion et à choisir celle-ci comme propriétaire.

prenez un exemple de deux entités Article et Tag. Chaque fois que vous voulez connecter un Article à une étiquette et vice-versa, c'est surtout L'Article qui est responsable de cette relation. Chaque fois que vous ajoutez un nouvel article, vous voulez le connecter avec des étiquettes existantes ou nouvelles. Votre formulaire de création d'Article soutiendra probablement cette notion et permettra de spécifier les tags directement. C'est pourquoi vous devez choisir L'Article comme côté propriétaire, car il rend le code plus compréhensible:

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

1
répondu Micheal Mouner Mikhail Youssif 2016-09-25 08:20:38