2013-08-23 105 views
1

我必須先確定我是一個總的初來乍到的教義,儘管我有足夠的瞭解SQL和PHP/Symfony的2學說2.2/2.2的Symfony:堅持實體與複合外鍵

所以,我創建關聯到一個SQL表這個問題類型的實體:

/** 
* IssueType 
* 
* @ORM\Table() 
* @ORM\Entity(repositoryClass="Blog\Bundle\CoreBundle\Entity\IssueTypeRepository") 
*/ 
class IssueType 
{ 
    /** 
    * @var integer 
    * 
    * @ORM\Column(name="id", type="integer") 
    * @ORM\Id 
    */ 
    private $id; 

    /** 
    * @var string 
    * 
    * @ORM\Column(name="name", type="string", length=255) 
    */ 
    private $name; 

    // Getters, setters... 
} 

我填充它,這樣的內容說,現在的表是:

id | name 
1 | Bande dessinée 
2 | Livre 
3 | Film 
4 | Disque 

現在我有這個其他實體,角色,它使用複合鍵,由一個普通的字符串(名稱)和外鍵(ID從問題類型)的:

/** 
* Role 
* 
* @ORM\Table() 
* @ORM\Entity(repositoryClass="Blog\Bundle\CoreBundle\Entity\RoleRepository") 
*/ 
class Role 
{ 
    /** 
    * @var IssueType 
    * 
    * @ORM\ManyToOne(targetEntity="Blog\Bundle\CoreBundle\Entity\IssueType") 
    * @ORM\JoinColumn(nullable=false) 
    * @ORM\Id 
    */ 
    private $issueType; 

    /** 
    * @var string 
    * 
    * @ORM\Column(name="name", type="string", length=255) 
    * @ORM\JoinColumn(nullable=false) 
    * @ORM\Id 
    */ 
    private $name; 

    // Getters, setters... 
} 

兩個表是通過數據庫中的教義正確生成。然而,儘管這應該是微不足道的,但我不能在我的生活中找到一個在這種情況下正確和成功堅持運作的例子。

我嘗試做的是以下幾點:

$manager = $this->getDoctrine()->getManager(); 

    $issueType = new IssueType(); 
    $issueType->setId(1); 

    $role = new Role(); 
    $role->setIssueType($issueType); 
    $role->setName('Dessinateur'); 

    $manager->persist($role); 
    $manager->flush(); 

我這樣嘗試堅持以下幾點:

Role: { 
    IssueType: {id: 1, name: ''}, 
    name: 'Dessinateur', 
} 

而我得到的是這個討厭的例外:

Entity of type Blog\Bundle\CoreBundle\Entity\Role has identity through a foreign entity Blog\Bundle\CoreBundle\Entity\IssueType, however this entity has no identity itself. You have to call EntityManager#persist() on the related entity and make sure that an identifier was generated before trying to persist 'Blog\Bundle\CoreBundle\Entity\Role'. In case of Post Insert ID Generation (such as MySQL Auto-Increment or PostgreSQL SERIAL) this means you have to call EntityManager#flush() between both persist operations. 

我明白它要我堅持第一個外國實體,但我不想這樣做,因爲外國問題類型ID#1已經存在於數據庫中,因此不需要持久化。當我沒有在註釋中指定任何'級聯'屬性時,它怎麼能問我?

BTY我試過,因爲它說,它預計結束與重複的輸入錯誤。

那麼,我該怎麼做才能使學說理解外國問題類型不應該被持續?

編輯

artmees提出了以下解決方案,工作正常:

$manager = $this->getDoctrine()->getManager(); 

$issueType = $manager->getRepository('BlogCoreBundle:IssueType')->find(1); 

$role = new Role(); 
$role->setIssueType($issueType); 
$role->setName('Dessinateur'); 

$manager->persist($role); 
$manager->flush(); 

然而,這意味着提高到能夠在不使用原則就可以避免數據庫的額外請求。由於我已經知道要使用的外部標識,是否有任何方法可以直接使用persist(),而不需要像從數據庫中實際檢索完整對象那樣的長度?

+0

據我所知(限定任何可能的公牛)。當你調用' - > find(1)'時,懶惰加載對象而不是完全加載它。當你將它傳遞給'Role()'對象時,它從對象的代理版本中獲得它所需的東西,在這方面它將是id(而不是整個對象)。 創建對象後,您需要調用persist(將對象排成數據庫),然後刷新以將隊列推送到數據庫。正確使用它可以確保您將正確的對象而不是新鮮的對象與隨機的,可能不正確的ID連接起來。 – qooplmao

回答

1

試試這個

$manager = $this->getDoctrine()->getManager(); 

$issueType = $manager->find('IssueTypeRepository', 1); 

$role = new Role(); 
$role->setIssueType($issueType); 
$role->setName('Dessinateur'); 

$manager->persist($role); 
$manager->flush(); 
+0

已經嘗試過了,正如我在描述結束時所說的那樣。導致重複錯誤。無論如何,我不想堅持問題類型,因爲它已經存在於數據庫中。 我不能在這裏做的是定義我的新$角色條目應該使用的issue_type的(已經存在的)外鍵。 – Zephyr

+0

我更新了代碼試試看它是否有效? 因爲'$ issueType'已經存在請嘗試獲取它[在此處查看文檔](http://docs.doctrine-project.org/en/2.0.x/reference/working-with-objects.html#querying) –

+0

它的工作原理,謝謝!但我有一種感覺,這不是最佳解決方案;這是對數據庫的額外的SQL請求,如果不使用Doctrine,我會避免這種請求。因此,我懷疑有更好的方法來做到這一點。 – Zephyr

0

我知道這是一個老的文章,但...

只需添加到artmees答案,如果你知道ID和你只是想插入,你不需要加載實體,只需使用參考。

$manager = $this->getDoctrine()->getManager(); 

$issueType = $manager->getReference('BlogCoreBundle:IssueType',1); 

$role = new Role(); 
$role->setIssueType($issueType); 
$role->setName('Dessinateur'); 

$manager->persist($role); 
$manager->flush(); 

這將創建一個具有該ID(1)的代理,這是您保存角色實體所需的全部內容。