2012-09-19 109 views
78

我正在開發使用Zend Framework 2和學說2.inversedBy和mappedBy有什麼區別?

雖然書面方式說明我的申請,我無法理解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; 

我做了快速搜索,發現以下,但我仍然困惑:

回答

127
  • 的mappedBy具有要在(雙向)的反轉側關聯
  • inversedBy具有要在(雙向)的持有端關聯指定指定

from doctrine documentation:

  • ManyToOn e始終是雙向關聯的擁有方。
  • OneToMany始終是雙向關聯的反面。
  • OneToOne關聯的擁有方是包含外鍵的表的實體。

參見http://docs.doctrine-project.org/en/latest/reference/unitofwork-associations.html

+1

奇怪的學說記錄器決定離開了一個多到一個雙向映射的YAML例子,大概最常用的! –

+2

@PeterWooster,最好的做法是使用註釋,因爲你有一個地方的實體的所有信息! –

+0

這也適用於多對多的關係。對於那些人:你可以自己選擇多對多的關聯。 – 11mb

20

在雙向關係同時具有持有端和逆側

的mappedBy:投入的雙向關係中的反向端要引用其持有端

InversedBy:放入雙向關係的擁有方參照其反面

AND

的mappedBy與OneToOne,一對多,或多對多映射聲明使用的屬性。

InversedBy用於OneToOne,ManyToOne或ManyToMany映射聲明的屬性。

注意事項: 雙向關係的擁有方包含外鍵的一面。

有兩個參考有關inversedBy和的mappedBy成學說文檔: First LinkSecond Link

+1

+1表示某些示例的鏈接。 – Marcos

38

上面的答案是不足以讓我明白了什麼是在深入研究之後怎麼回事,所以我越覺得我有辦法解釋它對那些像我一樣理解那樣掙扎的人來說是有意義的。

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; 
} 

這些類,如果你要運行命令生成模式(例如,bin/console doctrine:schema:update --force --dump-sql),你會發現,在分類表中沒有一個列上的任務。 (這是因爲它沒有列標註)

這裏要理解的重要一點是變量任務只在那裏,所以內部的教條引擎可以使用上面的引用它的mappedBy類的引用。現在...不要在這裏混淆,就像我是... 類別不是指類名稱,它指的是任務類上的屬性,稱爲'保護$類別'。

像明智的,在任務類的屬性$類別提到它是inversedBy =「任務」,請注意這是複數,這是不是類名的複數形式,而是因爲財產被稱爲「保護$任務'在類別類。

一旦你明白了這一點,就很容易理解inversedBy和mappedBy在做什麼以及如何在這種情況下使用它們。

在我的示例中引用外部鍵(如'tasks')的一方總是獲取inversedBy屬性,因爲它需要知道該類的哪個類(通過targetEntity命令)和該類的哪個變量(inversedBy =)工作向後「這樣說,並從中獲取類別信息。一個簡單的方法來記住這個,這個類將有foreignkey_id是需要反轉的那個。

與類別及其$ tasks屬性(不在表格中,記住,僅僅是用於優化目的的類的一部分)屬於MappedBy的「任務」,這會在兩個實體之間正式建立關係,所以教義現在可以安全地使用JOIN SQL語句而不是兩個單獨的SELECT語句。如果沒有mappedBy,則教條引擎不會從JOIN語句中知道它會在類Task中創建什麼變量來放置類別信息。

希望這解釋得更好一點。

+4

這是非常好的解釋和感謝您的努力。我來自Laravel雄辯的學說,這很難讓我理解這裏的邏輯。做得好。 'Category不是指CLASS NAME,它指的是所有我需要的名爲'protected $ category'的Task類的屬性。它不僅解決了我的問題,而且幫助我理解。 IMO的最佳答案:-) –

+0

謝謝,花了我一段時間來弄清楚這一點。很高興幫助:)。 –

+0

我也來自雄辯,這對我非常有幫助。我現在唯一的困難就是如何爲此設置setter/getter,我仍然在學習它的繩索 – Eman

1

5.9.1。擁有和反面

對於多對多關聯,您可以選擇擁有哪個實體,哪個是反面。從開發人員的角度來看,有一個非常簡單的語義規則來決定哪一方更適合成爲擁有方。您只需要問問自己,哪個實體負責連接管理,並將其視爲擁有方。

以兩個實體Article和Tag爲例。無論何時您想將文章連接到標籤,反之亦然,主要是負責這種關係的文章。無論何時添加新文章,您都希望將其與現有標籤或新標籤進行連接。您創建的文章形式可能會支持這個概念,並允許直接指定標籤。這就是爲什麼你應該選擇第二條爲持有端,因爲它使代碼更容易理解:

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