2013-04-09 58 views
5

我有以下的協會在我的數據庫(簡化版):複合鍵和形式

db schema

這是一個許多-to-many關聯,但與在接頭表中的屬性,所以I have to use One-To-Many/Many-To-One associations

我有一個表格,我可以在同一時間(主要靈感來自文檔How to Embed a Collection of Forms教程,因爲我想一個訂單項目添加儘可能多的關係,創建它。

當我發帖的形式,我收到以下錯誤:

Entity of type TEST\MyBundle\Entity\Relation has identity through a foreign entity TEST\MyBundle\Entity\Order, 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 'TEST\MyBundle\Entity\Relation'. 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.

因爲學說試圖堅持,因爲我對OneToMany關係cascade={"persist"}選項有關的順序Relation對象(S)我明白這個錯誤,但我怎麼能避免這種行爲。 ?

我試圖刪除cascade={"persist"}和手動堅持實體,但我得到了同樣的錯誤(因爲我需要flush()以獲得ID,當我這樣做,我也有同樣的錯誤消息)。
我也試圖detach()flush()Relation對象,但沒有運氣。

回答

1

我結束了我的Relation表創建分離的主鍵(而不是具有複合的一個)。
看起來這是一個骯髒的修復,我相信有更好的方法來處理這種情況,但它現在起作用。

這裏是我的Relations實體:

/** 
* Relation 
* 
* @ORM\Entity 
*/ 
class Relation 
{ 
    /** 
    * @var integer 
    * 
    * @ORM\Column(name="id", type="integer") 
    * @ORM\Id 
    * @ORM\GeneratedValue(strategy="AUTO") 
    */ 
    private $id; 

    /** 
    * @ORM\ManyToOne(targetEntity="Contact", inversedBy="relation") 
    */ 
    protected $contact; 

    /** 
    * @ORM\ManyToOne(targetEntity="Order", inversedBy="relation") 
    */ 
    protected $order; 

    /** 
    * @var integer 
    * 
    * @ORM\Column(name="invoice", type="integer", nullable=true) 
    */ 
    private $invoice; 

    //Rest of the entity... 

然後,我Order加入cascade={"persist"}選項上OneToMany關係:

/** 
* Orders 
* 
* @ORM\Entity 
*/ 
class Order 
{ 
    /** 
    * @ORM\OneToMany(targetEntity="Relation", mappedBy="order", cascade={"persist"}) 
    */ 
    protected $relation; 

    //Rest of the entity... 

的Et瞧!

1

您需要堅持並刷新原件,然後才能保留並刷新關係記錄。您在錯誤原因中100%正確。

我從你試圖添加圖表和秩序,關係到在同一時間接觸承擔?如果是這樣,您需要堅持並刷新訂單,然後才能保留並刷新關係。或者您可以將主鍵添加到關係表。

+0

你是對的,我想添加一個訂單,並在同一時間聯繫的關係。我試圖刷新順序,但後來我得到了關於「cascade = {」persist「}的需求的錯誤,如果我把它放回去,它會首先嚐試保存關係。你有沒有一個工作的例子?我找不到一個... – cheesemacfly 2013-04-09 19:28:29

+0

您需要手動持續關係。所有'cascade = {「persist」}'所做的是,如果你堅持一個與該設置有關係的實體,它會自動添加'$ em-> persist($ relationshipObject)'所以要解決你的問題,你需要離開關閉,然後手動保留關係對象,然後再次刷新。 – 2013-04-09 20:14:23

+0

但是,如果我嘗試刪除'cascade = {「persist」}',然後堅持/沖洗順序對象,我得到一個:'一個新的實體通過關係'TEST \ MyBundle \ Entity \ Orders#關係'未配置爲級聯實體的持久操作:TEST \ MyBundle \ Entity \ Relations ...'。我甚至嘗試在關係對象上使用'detach()',但沒有成功...... – cheesemacfly 2013-04-09 20:22:28

3

這個問題似乎獨特的,如果1)使用的是複合主鍵連接表,2)形成組件,以及3)連接表是由表單組件的「集合」字段建立的實體。我看到很多人有問題,但沒有很多解決方案,所以我想我會分享我的。

我想保持我的複合主鍵,因爲我想確保只有一個兩個外鍵的情況下將在數據庫中存在。使用 this entity setup爲例

/** @Entity */ 
class Order 
{ 
    /** @OneToMany(targetEntity="OrderItem", mappedBy="order") */ 
    private $items; 

    public function __construct(Customer $customer) 
    { 
     $this->items = new Doctrine\Common\Collections\ArrayCollection(); 
    } 
} 

/** @Entity */ 
class Product 
{ 
    /** @OneToMany(targetEntity="OrderItem", mappedBy="product") */ 
    private $orders; 
    ..... 

    public function __construct(Customer $customer) 
    { 
     $this->orders = new Doctrine\Common\Collections\ArrayCollection(); 
    } 
} 

/** @Entity */ 
class OrderItem 
{ 
    /** @Id @ManyToOne(targetEntity="Order") */ 
    private $order; 

    /** @Id @ManyToOne(targetEntity="Product") */ 
    private $product; 

    /** @Column(type="integer") */ 
    private $amount = 1; 
} 

我面臨的,如果我正在建立表單中的Order對象,即具有OrderItem秒的採集場的問題,我不能夠保存OrderItem的實體,而不首先保存了Order Entity(因爲Doctrine/SQL需要組合鍵的Order ID),但Doctrine EntityManager不允許保存OrderItem屬性的Order對象(因爲它堅持將它們一起保存) 。您不能關閉級聯,因爲它會抱怨您沒有先保存關聯的實體,並且在保存Order之前無法保存關聯的實體。真是個難題。 我的解決方案是刪除關聯的實體,保存Order,然後將關聯的實體重新引入Order對象並再次保存。首先,我創建了一個ArrayCollection的質量分配功能屬性$items

class Order 
{ 
    ..... 
    public function setItemsArray(Doctrine\Common\Collections\ArrayCollection $itemsArray = null){ 
    if(null){ 
     $this->items->clear(); 
    }else{ 
     $this->items = $itemsArray; 
    } 
    .... 
} 

然後在我的控制,我處理的形式進行訂購。

//get entity manager 
$em = $this->getDoctrine()->getManager(); 
//get order information (with items) 
$order = $form->getData(); 
//pull out items array from order 
$items = $order->getItems(); 
//clear the items from the order 
$order->setItemsArray(null); 
//persist and flush the Order object 
$em->persist($order); 
$em->flush(); 

//reintroduce the order items to the order object 
$order->setItemsArray($items); 
//persist and flush the Order object again): 
$em->persist($order); 
$em->flush(); 

它吮吸,你必須堅持並兩次刷新(詳見這裏Persist object with two foreign identities in doctrine)。但這是對你的理論,它的全部力量,肯定會使你陷入困境。但是謝天謝地,只有在創建新對象時才需要這樣做,而不是編輯,因爲對象已經在數據庫中。