inversedBy和mappedBy有什么区别?

Dev*_*per 98 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;
Run Code Online (Sandbox Code Playgroud)

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

And*_*den 153

  • 必须在(双向)关联的反向一侧指定mappedBy
  • inversedBy必须在(双向)关联的拥有方指定

来自学说文档:

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

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

  • @PeterWooster,最佳做法是使用Annotations,因为您可以在一个地方获得有关该实体的所有信息! (4认同)
  • @AndreasLinden广泛使用并不意味着最佳实践.使用注释来动态编写代码的东西永远不会被认为是最佳实践,它不是php native,甚至不包含在所有框架中.在一个地方拥有关于实体的所有信息是反论据.因为将所有代码分组到一个地方是一件好事吗?编写是一种痛苦,维护是一种痛苦,并减少了项目中的组织.最佳实践 ?咄. (4认同)
  • @JesusTheHun您正在比较苹果和梨。“所有代码”与“有关实体的所有信息”非常不同;) (3认同)

Jos*_*han 53

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

INTERNAL 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;
}
Run Code Online (Sandbox Code Playgroud)

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

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

同样明智的是,在Tasks类中,属性$ category提到它是inversedBy ="tasks",注意这是复数,这不是类的名称,而是因为该属性在类别中被称为'protected $ tasks'类.

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

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

与类别一样,它的$ tasks属性(不在桌面上记住,只是用于优化目的的类的一部分)是MappedBy'任务',这在两个实体之间正式建立关系,以便原则现在可以安全使用JOIN SQL语句而不是两个单独的SELECT语句.如果没有mappedBy,则学说引擎不会从JOIN语句中知道它将在类"Task"中创建什么变量来放置类别信息.

希望这能解释得更好一些.

  • 这是非常好的解释,并感谢您的努力.我来自Laravel Eloquent的学说,这对我来说很难理解这里的逻辑.做得好.`类别不是指类名,它指的是Task类中的属性,名为'protected $ category'.我需要的全部内容.它不仅解决了我的问题,而且帮助我理解了.IMO的最佳答案:-) (6认同)

ahm*_*mdy 20

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

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

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

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

inversedBy与OneToOne,多对一,或多对多映射声明使用的属性.

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

有两个关于inversedBy和mappedBy的参考文献到Doctrine Documentation: First Link,Second Link