В чем разница между inversedBy и mappedBy?
я разрабатываю свое приложение, используя Zend Framework 2 и доктрину 2.
при написании аннотаций я не могу понять разницу между mappedBy
и inversedBy
.
когда я должен использовать mappedBy
?
когда я должен использовать inversedBy
?
когда я должен использовать ни то, ни другое?
вот пример:
/**
*
* @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;
Я сделал быстрый поиск и нашел следующее, Но я все еще в замешательстве:
4 ответа:
- mappedBy должен быть указан на обратная сторона (двунаправленной) ассоциации
- inversedBy должен быть указан на владея сторону (двунаправленной) ассоциации
из документации доктрины:
- ManyToOne всегда является стороной владения двунаправленной ассоциацией.
- OneToMany всегда является обратной стороной двунаправленного ассоциация.
- сторона владельца ассоциации OneToOne-это сущность с таблицей, содержащей внешний ключ.
inversedBy и mappedBy используются ВНУТРЕННЯЯ ДОКТРИНА двигатель уменьшите количество запросов 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
) вы заметите, что в таблице категорий нет столбца для задач. (это потому, что на нем нет аннотации столбца)здесь важно понимать, что переменные задачи есть только там, поэтому внутренний движок доктрины можно использовать ссылку выше, которая говорит его mappedBy категории. Сейчас... не путайтесь здесь, как я был... категория не относится к имени класса, это относится к свойству в классе задач под названием "protected $category".
как мудрый, в классе задач свойство $category упоминает, что оно перевернуто= "задачи", обратите внимание, что это множественное число,это не множественное число имени класса, но только потому, что свойство называется "protected $tasks" в категория класс.
Как только вы поймете это, становится очень легко понять, что делают inversedBy и mappedBy и как их использовать в этой ситуации.
сторона, которая ссылается на внешний ключ, например "задачи" в моем примере, всегда получает атрибут inversedBy, потому что ему нужно знать, какой класс (через команду targetEntity) и какая переменная (inversedBy=) в этом классе "работает назад", так сказать, и получает информацию о категории. Простой способ чтобы помнить это, является класс, который будет иметь foreignkey_id является тот, который должен иметь inversedBy.
где как с категорией, так и с ее свойством $tasks (которого нет в таблице, помните, только часть класса для целей оптимизации) сопоставляется "tasks", это создает связь официально между двумя сущностями, так что теперь doctrine может безопасно использовать операторы JOIN SQL вместо двух отдельных операторов SELECT. Без mappedBy, доктрина двигатель не будет знайте, что из оператора JOIN он создаст какую переменную в классе 'Task' поместить информацию о категории.
надеюсь, это объясняет это немного лучше.
в двунаправленном отношении имеет как собственную сторону, так и обратную сторону
mappedBy: поместите в обратную сторону двунаправленного отношения, чтобы ссылаться на его собственную сторону
inversedBy: поместите в сторону владения двунаправленного отношения, чтобы ссылаться на его обратную сторону
и
mappedBy атрибут, используемый с отображением OneToOne, OneToMany или ManyToMany декларация.
inversedBy атрибут, используемый с объявлением отображения OneToOne, ManyToOne или ManyToMany.
обратите внимание : Сторона-владелец двунаправленной связи сторона, содержащая внешний ключ.
там две ссылки о inversedBy и mappedBy в документации доктрины : Первая Ссылка,Вторая Ссылка
5.9.1. Владение и обратная сторона
для многих-ко-многим ассоциаций вы можете выбрать, какой объект является владельцем, а какой обратной стороной. Существует очень простое семантическое правило, чтобы решить, какая сторона более подходит для того, чтобы быть стороной-владельцем с точки зрения разработчиков. Вам нужно только спросить себя, какой объект отвечает за управление соединением и выбрать его в качестве стороны-владельца.
возьмем пример двух сущностей Article и Tag. Всякий раз, когда вы хотите подключите статью к тегу и наоборот, это в основном статья, которая отвечает за это отношение. Всякий раз, когда вы добавляете новую статью, вы хотите связать ее с существующими или новыми тегами. Ваша форма создать статью, вероятно, поддержит это понятие и позволит указать теги напрямую. Вот почему вы должны выбрать статью Как владеющую сторону, так как это делает код больше понятно:
http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/association-mapping.html