2013-04-24 83 views
7

在最新的關於Symfony2的Doctrine試圖找出兩個對象之間的多重雙向關係。主義多重OneToMany/ManyToOne雙向完整性約束違反

個人擁有者對象有一個郵政地址,然後在一個集合中有多個二級地址,我刪除()該人,我希望它的所有地址也被刪除(但刪除一個地址不應該刪除一個人),但我得到這個錯誤 -

An exception occurred while executing 'DELETE FROM address WHERE id = ?' with 
params {"1":"fb5e47de-2651-4069-b85e-8dbcbe8a6c4a"}: 

[PDOException] SQLSTATE[23000]: Integrity constraint violation: 1451 
Cannot delete or update a parent row: a foreign key constraint fails 
(`db`.`address`, CONSTRAINT `FK_633704 C29C1004E` 
FOREIGN KEY (`person_id`) REFERENCES `person` (`id`)) 

class Person 
{ 

    /** 
    * @var Address postalAddress 
    * 
    * @ORM\OneToOne(targetEntity="Address", cascade={"all"}, orphanRemoval=true) 
    * @ORM\JoinColumn(onDelete="cascade") 
    */ 
    private $postalAddress; 

    /** 
    * @var \Doctrine\Common\Collections\Collection otherAddresses 
    * 
    * @ORM\OneToMany(targetEntity="Address", mappedBy="person", cascade={"all"}, orphanRemoval=true) 
    */ 
    private $otherAddresses; 


} 

class Address 
{ 

    /** 
    * @var Person person 
    * 
    * @ORM\ManyToOne(targetEntity="Person", inversedBy="postalAddress, otherAddresses") 
    * @ORM\JoinColumn(nullable=false) 
    */ 
    private $person; 
} 

我想這可能是因爲

inversedBy="postalAddress, otherAddresses" 

我不認爲多重inversedBy是支持;那麼我也試圖改變

@ORM\JoinColumn(nullable=false) 

是可以爲空,但我仍然得到錯誤。

這顯然不是微不足道的人物/地址示例,而是更復雜的東西,但這是我對抽象的最佳嘗試。

我確定我錯過了一些明顯的東西。誰能幫忙?

+1

我認爲這個問題可能是因爲你試圖說多對一的OneToOne反而不是ManyToOne。你試過了嗎?* @ORM \ ManyToOne(targetEntity =「Person」,inversedBy =「otherAddresses」)* @ORM \ OneToOne(targetEntity =「Person」) * @ORM \ JoinColumn(nullable = false)''方式學說處理級聯,即使它不改變模式。 – 2013-04-24 19:46:17

回答

2

破碎關係定義

當你在做什麼,可以從純邏輯的角度看是有意義的,它不會從一個關係型數據的角度來看,特別是沒有從學說的透視感覺。

主義正在努力維持3個不同的關係:

  • 地址(擁有方)[雙向] $人--Many:One--> $ otherAddresses
  • 地址(擁有方)[雙向] $ person --Many:One--> $郵政地址
  • (擁有方)[單向] $郵寄地址--One:One--> $ ID 地址

你看這個問題?

使用關係標準來解決這個問題。

這裏簡單的解決方案是使用非常常見的設計模式來設置集合的主要。從本質上講,你只需要一個關係:

  • 地址(擁有方)[雙向] $人--Many:One--> $ otherAddresses

然後,添加以解決財產將該地址定義爲主要的。在Person和Address實體Programattically處理這個問題:

Class Person 
{ 
    . . . 
    public function getPrimaryAddress() { 
     if (null === $this->primaryAddress) { 
      foreach($this->getOtherAddresses() as $address) { 
       if ($address->isPrimary()) { 
        $this->primaryAddress = $address; 
        break; 
       } 
      } 
     } 

     return $this->primaryAddress; 
    } 

    // similar for the setter, update the old address as not primary if there is one, set the new one as primary. 
} 

使用兩種不同的關係,但如果你從人保持一比一的關係單向到地址不要過流

,問題就解決了。

  • 地址(擁有方)[雙向] $人--Many:One--> $ otherAddresses
  • (擁有方)[單向] $郵寄地址--One:One-->地址

儘管如此,你仍然會遇到麻煩,因爲學說會抱怨如果: - 主要PostalAddress)地址沒有雙方爲許多:一個定義。 (所以你的「主要」地址也必須在$otherAddresses集合中)。 - 嘗試刪除或級聯刪除和更新會導致這兩種關係相互衝突,原則的關係約束的「交叉流」,因此您必須以編程方式處理這些操作。

+0

注意:使用條件可以使'Person :: getPrimaryAddress'方法變得更清晰。 – 2017-10-17 20:17:17

+1

哦,我4年前問過這個問題。現在解決方案對我來說更加明顯,但當時我還不確定。無論如何感謝您的回答! – gingerCodeNinja 2017-10-20 15:49:02

+1

您的問題首先在Google搜索中彈出。雖然我認爲你現在已經找到了解決問題的方法,但我想幫助下一位在這裏找到自己的方式的失敗的編碼員。 – 2017-10-21 17:44:33