2013-04-09 3 views
5

나는 내 데이터베이스 (간체 버전) 다음과 같은 연결을 가지고 :복합 키와 형태

db schema

이것은 많은-많은-으로 연결하지만 가입 테이블에 속성을 가진, 그래서 I have to use One-To-Many/Many-To-One associations입니다.

은 내가 주로 문서에서 How to Embed a Collection of Forms 튜토리얼에서 영감을 동시에 (그것을 내가 한 주문 항목에 원하는만큼의 관계를 추가하고 만들 수있는 형태를 가지고있다.

내가 양식을 게시 할 때, 교리 내가 OneToMany 관계에 cascade={"persist"} 옵션이 있기 때문에 순서에 관한 Relation 객체 (들)을 유지하려고하기 때문에 나는이 오류를 이해

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.

하지만 어떻게 내가이 문제를 방지 할 수 있습니다 나는 다음과 같은 오류가 발생합니다. ?

나는 cascade={"persist"}을 제거하고 엔티티를 수동으로 유지하려고 시도했지만 동일한 오류가 발생합니다. 왜냐하면 ID를 얻기 위해 flush() 주문을해야하기 때문에 동일한 오류 메시지가 나타납니다.
flush() 전에 detach()Relation 개체를 시도했지만 행운이 없습니다.

답변

1

Relation 테이블에 분리 된 기본 키를 만들었습니다 (합성 키 대신).
더티 픽스처럼 보입니다.이 상황을 처리하는 더 좋은 방법이있을 것이라고 확신하지만 지금은 효과가 있습니다.

/** 
* 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으로 OneToMany 관계에 cascade={"persist"} 옵션을 추가 :

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

    //Rest of the entity... 

잇함으로써 해결할 수

여기 내 Relations 실체!

1

관계 레코드를 유지하고 플러시하기 전에 원본을 유지하고 플러시해야합니다. 오류의 원인이 100 % 정확합니다.

다이어그램에서 추가 및 순서와 연락처의 관계를 동시에 가정합니다. 그렇다면 관계를 유지하고 플러시하기 전에 주문을 유지하고 플러시해야합니다. 또는 관계 테이블에 기본 키를 추가 할 수 있습니다.

+0

당신이 맞습니다. 나는 동시에 연락 할 수있는 명령과 관계를 추가하려고합니다. 전에 명령을 내리려고했지만'cascade = { "persist"} "의 필요성에 대한 오류를 얻었고 다시 넣으면 관계를 먼저 저장하려고합니다. 당신은 어딘가에서 실제 사례를 가지고 있습니까? 나는 하나를 찾을 수 없습니다 ... – cheesemacfly

+0

당신은 수동으로 관계를 지속해야합니다. 모든'cascade = { "persist"}'는 당신이 그 엔티티와 관계가있는 엔티티를 지속한다면'$ em-> persist ($ relationshipObject)'를 자동으로 추가 할 것입니다. 그래서 문제를 해결하기 위해서는 해제하고 수동으로 관계 개체를 유지하고 두 번째 플러시를 수행합니다. –

+0

''cascade = { "persist"}'를 제거한 다음 order 객체를 먼저 유지/플러시하려고하면 'TEST \ MyBundle \ Entity \ Orders # relations'관계를 통해 새로운 엔티티를 찾았습니다. TEST \ MyBundle \ Entity \ Relations ... '엔티티에 대한 지속 작업을 계단식으로 구성하지 않았습니다. 나는 관계 객체에'detach()'를 사용하려했지만 성공하지 못했습니다 ... – cheesemacfly

3

이 문제는 1) 합성 키가있는 조인 테이블, 2) 양식 구성 요소 및 3) 조인 테이블이 양식 구성 요소의 '모음'필드에 의해 작성되는 개체 인 경우 고유 한 것으로 보입니다. 많은 사람들이 문제는 있지만 해결책은별로 없다는 것을 알았습니다. 그래서 저는 제 생각을 나눌 것이라고 생각했습니다.

두 개의 외래 키 중 하나만 인스턴스가 데이터베이스에 유지되도록하려면 복합 기본 키를 유지하려고했습니다.예를 들어

/** @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; 
} 

내가 OrderItem의 Collection 필드를 가진 형태로 Order 객체를 구축한다면 내가 직면 한 문제로 this entity setup을 사용하여, 나는하지 않고 엔티티를 OrderItem에 저장 할 수 없을 것입니다 (Doctrine/SQL은 복합 키의 순서 ID가 필요함) Doctrine EntityManager는 OrderItem 속성을 가진 Order 객체를 저장할 수 없도록했습니다 (대량 객체를 함께 저장하기를 원하기 때문에). . 연결된 엔티티를 먼저 저장하지 않았다고 불평 할 것이므로 캐스케이드를 끌 수 없으며 Order을 저장하기 전에 연결된 엔티티를 저장할 수 없습니다. 이 얼마나 수수께끼. 내 솔루션은 연결된 엔터티를 제거하고 Order을 저장 한 다음 관련 엔터티를 Order 개체에 다시 적용하고 다시으로 저장합니다. 그래서 일단 내가있는 ArrayCollection의 질량 할당 기능은 내가 주문의 양식을 처리 내 컨트롤러에

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

$items 그리고 속성 만들었습니다.

//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를 더 참조). 그러나 그것은 당신을위한 교리입니다. 모든 힘으로, 당신을 묶어 둘 수 있습니다. 그러나 고맙게도 객체가 이미 데이터베이스에 있기 때문에 편집이 아닌 새 객체를 만들 때만 수행하면됩니다.