В чем разница между inversedBy и mappedBy?

Я разрабатываю свое приложение, используя Zend Framework 2 и Doctrine 2.

При написании аннотаций я не могу понять разницу между mappedBy и inversedBy .

Когда следует использовать mappedBy ?

Когда следует использовать inversedBy ?

Когда я не должен использовать ни то, ни другое?

Вот пример:

  /** * * @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; 

Я сделал быстрый поиск и нашел следующее, но я все еще смущен:

  • пример 1
  • пример 2
  • пример 3

  • mappedBy должно быть указано на обратной стороне (двунаправленной) ассоциации
  • inversedBy должен быть указан на стороне владельца (двунаправленной) ассоциации

из документации доктрины:

  • ManyToOne всегда является обладающей двунаправленной ассоциацией.
  • OneToMany всегда является обратной стороной двунаправленной связи.
  • Собственной стороной ассоциации OneToOne является сущность с таблицей, содержащей внешний ключ.

См. http://docs.doctrine-project.org/en/latest/reference/unitofwork-associations.html.

Ответных ответов было недостаточно для того, чтобы я понял, что происходит, поэтому, вникая в это, я думаю, что у меня есть способ объяснить это, что будет иметь смысл для людей, которые изо всех сил пытались понять.

inverseedBy и mappedBy используются движком INTERNAL DOCTRINE, чтобы уменьшить количество SQL-запросов, которые он должен выполнить, чтобы получить нужную вам информацию. Чтобы быть ясным, если вы не добавляете inversedBy или mappedBy, ваш код будет работать, но не будет оптимизирован .

Так, например, посмотрите на следующие классы:

 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; } 

Эти классы, если вы должны были запустить команду для создания схемы (например, bin/console doctrine:schema:update --force --dump-sql ), вы заметите, что в таблице Category нет столбца для нее для задач , (это потому, что на нем нет аннотации столбца)

Здесь важно понять, что переменные задачи существуют только там, поэтому механизм внутренней доктрины может использовать ссылку выше, которая гласит его отображаемую категорию. Теперь … не путайте здесь, как я был … Категория НЕ относится к ИМЯ КЛАССА , ссылаясь на свойство в классе Task, называемом «защищенная категория».

Как и мудрый, в классе «Задачи» свойство $ category упоминает, что оно инвертированоBy = «задачи», обратите внимание, что это множественное число, это НЕ ПЛОХАЛЬНОЕ НАЗВАНИЕ КЛАССА , а только потому, что свойство называется «защищенными задачами» в категории класс.

Как только вы это понимаете, становится очень легко понять, что происходит с обратными и сопоставленными и как их использовать в этой ситуации.

Сторона, которая ссылается на внешний ключ, такой как «задачи» в моем примере, всегда получает атрибут inversedBy, потому что ему нужно знать, какой класс (через команду targetEntity) и какую переменную (inversedBy =) для этого класса «работать назад», так что говорить и получать информацию о категории. Легкий способ запомнить это, это класс, который будет иметь foreignkey_id, который должен иметь inversedBy.

Где, как и в случае с категорией и свойством $ tasks (которое не указано в таблице, только часть класса для целей оптимизации) является MappedBy 'tasks', это создает отношения официально между двумя объектами, чтобы доктрина теперь могла безопасно используйте JOIN SQL-инструкции вместо двух отдельных операторов SELECT. Без mappedBy механизм доктрины не будет знать из оператора JOIN, что он создаст какую переменную в классе «Задача» для размещения информации о категории.

Надеюсь, это объяснит это немного лучше.

В двунаправленном отношении имеет как собственную сторону, так и обратную сторону

mappedBy : положить в обратную сторону двунаправленного отношения. Обратиться к своей стороне

inversedBy : положить в Собственную сторону двунаправленного отношения Чтобы ссылаться на свою обратную сторону

А ТАКЖЕ

атрибут mappedBy, используемый с объявлением отображения OneToOne, OneToMany или ManyToMany.

inversedBy, используемый с объявлением отображения OneToOne, ManyToOne или ManyToMany.

Примечание . Собственная сторона двунаправленного отношения – сторона, которая содержит внешний ключ.

там две ссылки о inversedBy и mappedBy в документацию Doctrine: первая ссылка , вторая ссылка

5.9.1. Собственная и обратная сторона

Для ассоциаций «многие-ко-многим» вы можете выбрать, какая сущность является собственностью, а какая наоборот. Существует очень простое семантическое правило, чтобы решить, какая сторона больше подходит для использования с точки зрения разработчиков. Вам нужно только спросить себя, какая организация несет ответственность за управление подключением и выбирает это как принадлежащую стороне.

Возьмем пример двух объектов Article и Tag. Всякий раз, когда вы хотите связать статью с тегом и наоборот, в основном эта статья несет ответственность за это отношение. Всякий раз, когда вы добавляете новую статью, вы хотите связать ее с существующими или новыми тегами. Форма «Создать статью», вероятно, поддерживает это понятие и позволяет напрямую указывать теги. Вот почему вы должны выбрать статью как обладающую стороной, поскольку она делает код более понятным:

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