inversedBy 和 mappedBy 有什么区别?

2022-08-30 07:17:40

我正在使用Zend Framework 2和Therness 2开发我的应用程序。

在编写注释时,我无法理解 和 之间的区别。mappedByinversedBy

我应该什么时候使用?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
  • mappedBy 必须在(双向)关联的反面端指定
  • inversedBy 必须在(双向)关联的所属方指定

来自学说文档:

  • ManyToOne始终是双向关联中的拥有方。
  • OneToMany 始终是双向关联的反面。
  • 一对一关联的所属方是具有包含外键的表的实体。

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


答案 2

上面的答案不足以让我理解发生了什么,所以在深入研究之后,我认为我有一种解释它的方法,对于那些像我一样努力理解的人来说是有意义的。

内部 DOCTRINE 引擎使用 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;
}

如果要运行命令以生成架构(例如,),您会注意到 Category 表上没有用于任务的列,这些类。(这是因为它上面没有列注释)bin/console doctrine:schema:update --force --dump-sql

这里要理解的重要一点是,变量任务只在那里,所以内部教义引擎可以使用它上面的引用,它说它的mappedBy Category。现在。。。不要像我以前一样在这里感到困惑...类别不是指类名,它指的是 Task 类上名为“受保护的$category”的属性。

同样明智的是,在 Tasks 类上,属性$category提到它是 inversedBy=“tasks”,请注意这是复数形式,这不是类名的复数形式,而只是因为该属性在 Category 类中称为“受保护的$tasks”。

一旦你理解了这一点,就很容易理解inversedBy和mappedBy在做什么,以及如何在这种情况下使用它们。

在我的示例中引用外键(如“tasks”)的一方总是获得inversedBy属性,因为它需要知道该类上的哪个类(通过targetEntity命令)和哪个变量(inversedBy=)来“向后工作”,可以这么说并从中获取类别信息。记住这一点的一个简单方法是,具有foreignkey_id的类是需要反转By的类。

与类别一样,其$tasks属性(不在表上,请记住,只是用于优化目的的类的一部分)是MappedBy“任务”,这正式创建了两个实体之间的关系,因此该原则现在可以安全地使用JOIN SQL语句而不是两个单独的SELECT语句。如果没有mappedBy,doctrine引擎将无法从JOIN语句中知道它将在类“Task”中创建哪个变量来放置类别信息。

希望这能更好地解释它。


推荐