inversedBy和mappedBy有什么区别?
我正在使用Zend Framework 2和Doctrine 2开发我的应用程序。
在写注释时,我无法理解mappedBy
和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;
我做了一个快速search,发现了以下内容,但我仍然感到困惑:
- 例子1
- 例2
- 例3
- mappedBy必须在(双向)关联的反面指定
- 反向必须在(双向)关联的拥有方面指定
从学说文件:
- ManyToOne始终是双向关联的拥有者。
- OneToMany永远是双向关联的反面。
- OneToOne关联的拥有方是具有包含外键的表的实体。
见http://docs.doctrine-project.org/en/latest/reference/unitofwork-associations.html
上面的答案不足以让我理解发生了什么事情,所以在深入研究之后,我想我可以有一种解释方式,这对那些像我一样理解那样挣扎的人来说是有意义的。
inversedBy和mappedBy由INTERNAL DOCTRINE引擎使用,以减less获取所需信息所需的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
),您将注意到,类别表没有任务列。 (这是因为它没有列注释)
这里要理解的重要一点是,variables任务只是在那里,所以内部的教条引擎可以使用上面的引用它的映射的类别。 现在…不要在这里混淆,就像我是… 类别不是指类名称 ,它是指称为“保护$类别”的任务类的属性。
就像明智的一样,在Tasks类中属性$ category提到它是inversedBy =“tasks”,注意这是复数, 这不是类名的多less ,只是因为这个属性在类别中被称为“protected $ tasks”类。
一旦你明白了这一点,就很容易理解这种情况是由inversedBy和mappedBy在做什么以及如何使用它们的。
在我的示例中引用外部键(如“任务”)的一面总是获取inversedBy属性,因为它需要知道该类(通过targetEntity命令)和该类上的哪个variables(inversedBy =)“倒退”说出并从中获取类别信息。 一个简单的方法来记住这个,这个类将有foreignkey_id是需要反转的那个。
与类别一样,它的$ tasks属性(不在表格中,记住,只是为了优化目的而只是类的一部分)是MappedBy的“任务”,这就build立了两个实体之间的正式关系,所以教条现在可以安全使用JOIN SQL语句而不是两个单独的SELECT语句。 如果没有映射,教条引擎不会从JOIN语句中知道它将在类“任务”中创build什么variables来放置类别信息。
希望这个解释好一点。
双向关系既有拥有方也有对立方
mappedBy :放入双向关系的反面参照它自己的一面
inversedBy :置于双向关系的拥有方面指其反面
和
与OneToOne,OneToMany或ManyToMany映射声明一起使用的mappedBy属性。
与OneToOne,ManyToOne或ManyToMany映射声明一起使用的inversedBy属性。
注意 :双向关系的拥有方包含外键的一面。
有两个关于反向的引用,并被映射为主义文档: First Link , Second Link
5.9.1。 拥有和反面
对于“多对多”关联,您可以select拥有哪个实体,哪个实体为反面。 从开发人员的angular度来看,有一个非常简单的语义规则来决定哪一方更适合作为拥有方。 您只需要问问自己,哪个实体负责连接pipe理,并将其作为自己的一方。
以两个实体Article和Tag为例。 每当你想连接一个文章到一个标签,反之亦然,这是主要负责这个关系的文章。 无论何时添加新文章,您都希望将其与现有标签或新标签进行连接。 你创build的文章forms可能会支持这个概念,并允许直接指定标签。 这就是为什么你应该select文章作为自己的一面,因为它使代码更容易理解:
http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/association-mapping.html