inversedBy和mappedBy有什么区别?

时间:2012-09-19 11:33:01

标签: php doctrine-orm

我正在使用Zend Framework 2和Doctrine 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;

我做了一个快速搜索并找到了以下内容,但我仍感到困惑:

4 个答案:

答案 0 :(得分:148)

    必须在(双向)关联的反面中指定
  • mappedBy
  • inversedBy 必须在(双向)关联的拥有方上指定

来自学说文档:

  • ManyToOne始终是双向关联的拥有方。
  • OneToMany始终是双向关联的反面。
  • OneToOne关联的拥有方是包含外键的表的实体。

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

答案 1 :(得分:50)

上面的答案不足以让我理解发生的事情,所以在深入研究之后我想我有办法解释它对那些像我理解的那样挣扎的人有意义。

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表中没有用于任务的列。 (这是因为它上面没有列注释)

这里要理解的重要一点是变量任务只在那里,所以内部学说引擎可以使用它上面的引用,它表示其mappedBy类别。现在......不要在这里感到困惑,就像我...... 类别不是指类名称,它指的是Task类中的属性名为' protected $类别'

同样明智的是,在Tasks类中,属性$ category提到它是inversedBy ="任务",注意这是复数,这不是类别名称的多数,但这只是因为该财产被称为“受保护的任务”。在Category类中。

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

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

与类别一样,并且其$ tasks属性(不在桌面上记住,只是用于优化目的的类的一部分)是MappedBy' tasks',这在正确的关系之间创建关系两个实体,以便doctrine现在可以安全地使用JOIN SQL语句而不是两个单独的SELECT语句。没有mappedBy,学说引擎就不会从JOIN语句中知道它将在类中创建什么变量'任务'把类别信息。

希望这能解释得更好。

答案 2 :(得分:20)

双向关系既有拥有方又有反方

mappedBy :放入双向关系的反面要引用它自己的一面

inversedBy :放入双向关系的拥有方面来引用其反面

mappedBy 属性与OneToOne,OneToMany或ManyToMany映射声明一起使用。

用于OneToOne,ManyToOne或ManyToMany映射声明的

inversedBy 属性。

注意: 双向关系的拥有方是包含外键的一方。

有两个关于inversedBy和mappedBy的参考文献到Doctrine文档中: First LinkSecond Link

答案 3 :(得分:2)

5.9.1。拥有和反面

对于多对多关联,您可以选择哪个实体是拥有者,哪个实体是反面。从开发人员的角度来看,有一个非常简单的语义规则来决定哪一方更适合作为拥有方。您只需要问问自己,哪个实体负责连接管理,并选择作为拥有方。

以两个实体Article和Tag为例。每当您想要将文章连接到标签时,反之亦然,主要是文章负责这种关系。每当您添加新文章时,您都希望将其与现有标签或新标签相关联。您的创建文章表单可能会支持此概念,并允许直接指定标记。这就是为什么你应该选择文章作为拥有方,因为它使代码更容易理解:

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