“被反转”和“被映射”的区别是什么?

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

While writting annotations, I am unable to understand the difference between mappedBy and 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;

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

79207 次浏览
  • MappedBy 必须在(双向)关联的 倒过来上指定
  • 必须在(双向)关联的 owning side上指定

根据理论文件:

  • ManyToOne is always the owning side of a bidirectional assocation.
  • OneTomany 总是双向关联的反面。
  • OneToOne 关联的拥有方是具有包含外键的表的实体。

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

在双向关系中,既有所有者的一面,也有反向者的一面

MappedBy : 放入双向关系的反向一侧以引用实体所属一侧的字段

双向关系的拥有方: 指实体的反面的字段

AND

MappedBy 属性与 OneToOne、 OneTomany 或 ManyTomany 映射声明一起使用。

inversedBy attribute used with the OneToOne, ManyToOne, or ManyToMany mapping declaration.

注意 : 双向关系中包含外键的所有方。

there two reference about inversedBy and mappedBy into Doctrine Documentation : 第一个链接第二个链接

以上的答案并不足以让我理解到底发生了什么,所以在更深入地研究之后,我想我有办法解释这个问题,对于那些像我一样努力去理解的人来说,这是有意义的。

内部原则引擎使用到 减少 SQL 查询的数量,它必须这样做才能获得您需要的信息。要清楚的是,如果你不添加反转或映射通过您的代码将仍然有效,但不会是 优化

例如,看看下面的类:

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 $type”。

同样明智的是,在 Tasks 类中,属性 $type 提到它的值是 overseBy = “ asks”,注意这是复数形式的,这不是班名的复数形式,但仅仅是因为该属性在 Category 类中被称为“ protected $asks”。

Once you understand this it becomes very easy to understand what inversedBy and mappedBy are doing and how to use them in this situation.

在我的例子中,引用外键(比如“ asks”)的那一边总是会得到反向 By 属性,因为它需要知道该类上的哪个类(通过 targetEntity 命令)和哪个变量(反向 By =)来“向后工作”,以便从中获取类别信息。要记住这一点,一个简单的方法是,使用 foreignkey _ id 的类是需要颠倒 By 的类。

与 type 一样,它的 $asks 属性(不在表中,只是类的一部分,用于优化目的)是 MappedBy‘ asks’,这在两个实体之间正式创建了关系,因此学说现在可以安全地使用 JOIN SQL 语句,而不是两个单独的 SELECT 语句。如果没有 mappedBy,学说引擎就不会从 JOIN 语句中知道它将在类“ Task”中创建哪个变量来放置类别信息。

希望这个能解释得更清楚一点。

5.9.1拥有及反面

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

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

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