2016-03-31 23 views
2

I (eklentiler ve güncellemeler ile) members ithalat toplu üzerinde çalışıyorum çalışmak için deneyin.Doctrine2 toplu alma varlıklar gibi <code>Member</code>, <code>Client</code>, <code>Group</code>, <code>...</code> bir sürü büyük bir proje için başka bir varlık

Doktrin doc toplu ithalatla ilgili bölümü okuduktan sonra, ben bu kodu uyguladık: Ben Member varlıklar dizisi işlemek toplu istediğinizde, Şimdi

$batchSize = 20; 
$i   = 0; 

foreach ($entities as $entity) 
{ 
    $this->getEntityManager()->persist($entity); 

    if (($i % $batchSize) === 0) 
    { 
     $this->getEntityManager()->flush(); 
     $this->getEntityManager()->clear(); 
    } 
} 

$this->getEntityManager()->flush(); 
$this->getEntityManager()->clear(); 

, Doktrin boş veri eklemeye çalıştığınızda Member ve Group arasında herhangi ilişkiler bulunmamaktadır istisna

An exception occurred while executing 'INSERT INTO groups ... atılır ve Group şirketle alakalı tamamen başka tabloya ... içine

Bu garip davranış hakkında bir fikrin var mı?

DÜZENLEME

Kısa haritalama ayrıntıları:

/** 
* @ORM\Entity 
* @ORM\Table(name="members") 
*/ 
class Member 
{ 
    // some properties ... 

    /** 
    * @ORM\ManyToOne(targetEntity="Client", inversedBy="members", cascade={"persist", "merge"}) 
    * @ORM\JoinColumn(name="client_id", referencedColumnName="id", onDelete="CASCADE") 
    */ 
    protected $client; 

    /** 
    * @return Client 
    */ 
    public function getClient() 
    { 
     return $this->client; 
    } 

    /** 
    * @param Client $client 
    * 
    * @return $this 
    */ 
    public function setClient(Client $client) 
    { 
     $this->client = $client; 

     return $this; 
    } 
} 

/** 
* @ORM\Entity 
* @ORM\Table(name="clients") 
*/ 
class Client 
{ 
    /** 
    * @ORM\OneToMany(targetEntity="Member", mappedBy="client", cascade={"persist", "remove", "merge"}, fetch="EXTRA_LAZY") 
    */ 
    protected $members; 

    /** 
    * @ORM\ManyToOne(targetEntity="Group", inversedBy="clients", cascade={"persist", "merge"}) 
    * @ORM\JoinColumn(name="clients_id", referencedColumnName="id", onDelete="SET NULL") 
    */ 
    protected $group; 

    public function __construct() 
    { 
     $this->members = new ArrayCollection(); 
    } 

    /** 
    * @return ArrayCollection 
    */ 
    public function getMembers() 
    { 
     return $this->members; 
    } 

    /** 
    * @param $members 
    * 
    * @return $this 
    */ 
    public function setMembers($members) 
    { 
     $this->members = new ArrayCollection(); 

     return $this->addMembers($members); 
    } 

    /** 
    * @param $members 
    * 
    * @return $this 
    */ 
    public function addMembers($members) 
    { 
     foreach ($members as $member) 
     { 
      $this->addMember($member); 
     } 

     return $this; 
    } 

    /** 
    * @param Member $member 
    * 
    * @return $this 
    */ 
    public function addMember(Member $member) 
    { 
     $this->members->add($member); 
     $member->setClient($this); 

     return $this; 
    } 

    /** 
    * @param Member $member 
    * 
    * @return $this 
    */ 
    public function removeMember(Member $member) 
    { 
     if ($this->members->contains($member)) 
     { 
      $this->members->removeElement($member); 
     } 

     return $this; 
    } 

    /** 
    * @param $members 
    * 
    * @return $this 
    */ 
    public function removeMembers($members) 
    { 
     foreach ($members as $member) 
     { 
      $this->removeMember($member); 
     } 

     return $this; 
    } 

    /** 
    * @param Group $group 
    * 
    * @return $this 
    */ 
    public function setGroup(Group $group = null) 
    { 
     $this->group = $group; 

     return $this; 
    } 

    /** 
    * @return Group 
    */ 
    public function getGroup() 
    { 
     return $this->group; 
    } 
} 

/** 
* @ORM\Entity 
* @ORM\Table(name="groups") 
*/ 
class Group 
{ 
    /** 
    * @ORM\OneToMany(targetEntity="Client", mappedBy="group") 
    */ 
    protected $clients; 

    public function __construct() 
    { 
     $this->clients = new ArrayCollection(); 
    } 

    /** 
    * @return ArrayCollection 
    */ 
    public function getClients() 
    { 
     return $this->clients; 
    } 

    /** 
    * @param $clients 
    * 
    * @return $this 
    */ 
    public function setClients($clients) 
    { 
     $this->clients = new ArrayCollection(); 

     return $this->addClients($clients); 
    } 

    /** 
    * @param $clients 
    * 
    * @return $this 
    */ 
    public function addClients($clients) 
    { 
     foreach ($clients as $client) 
     { 
      $this->addClient($client); 
     } 

     return $this; 
    } 

    /** 
    * @param Client $client 
    * 
    * @return $this 
    */ 
    public function addClient(Client $client) 
    { 
     if (!$this->clients->contains($client)) 
     { 
      $this->clients->add($client); 
      $client->setGroup($this); 
     } 

     return $this; 
    } 

    /** 
    * @param $clients 
    * 
    * @return $this 
    */ 
    public function removeClients($clients) 
    { 
     foreach ($clients as $client) 
     { 
      $this->removeClient($client); 
     } 

     return $this; 
    } 

    /** 
    * @param Client $client 
    * 
    * @return $this 
    */ 
    public function removeClient(Client $client) 
    { 
     if ($this->clients->contains($client)) 
     { 
      $this->clients->removeElement($client); 
      $client->setGroup(null); 
     } 

     return $this; 
    } 
} 

Ve hata tipi ise:

An exception occurred while executing 'INSERT INTO groups ... SQLSTATE[23502]: Not null violation: 7 ERROR: null value in column "label" violates not-null constraint DETAIL: Failing row contains (60, null, f, null, f, null, null).

EDIT2

Bu tablo oluşturma açıklamasıdır (kullanarak postgresql):

CREATE TABLE groups (
    id integer NOT NULL, 
    tempref character varying(255) DEFAULT NULL::character varying, 
    prorated_basis boolean NOT NULL, 
    fixed_price_amount double precision, 
    is_indexed boolean, 
    pricing_grid pricing[], 
    label character varying(255) NOT NULL 
); 

CREATE SEQUENCE groups 
    START WITH 1 
    INCREMENT BY 1 
    NO MINVALUE 
    NO MAXVALUE 
    CACHE 1; 

ALTER SEQUENCE groups_id_seq OWNED BY groups.id; 

ALTER TABLE ONLY pricing_groups ALTER COLUMN id SET DEFAULT nextval('groups_id_seq'::regclass); 

ALTER TABLE ONLY groups 
    ADD CONSTRAINT groups_pkey PRIMARY KEY (id); 
+0

şansın Eğer soruya bu iki sınıfın haritalama ayrıntıları eklemek olabilir? Bu döngüde ilerlemek için bir hata ayıklayıcısını kullanmayı denediniz mi ve bu özel durumun yalnızca ilk döngü yinelemesinde mi yoksa daha sonraki iterasyonlarda mı gerçekleştiğini görmek için denediniz mi? – Fge

+0

Merhaba Fge, geç cevap için üzgünüm ... Bu konu hakkında daha fazla bilgi almak için lütfen EDIT'imi kontrol edin. zaman – ceadreak

+0

için teşekkürler ben veritabanı tablosu yapısı ile uyumlu olması görünmüyor bir ayıklayıcı ancak hata floş – ceadreak

cevap

1

Hatanın nedenini açıklayabilirim, ancak bunun nedenini tahmin etmem ve yalnızca bunun hata ayıklama işlemi sırasında nelere bakmanız gerektiğine dair bazı ipuçları verir.

Açıkladığınız gibi, bir istemcinin parçası olan ve bir grubun parçası olan üyeleri güncelleştiriyorsunuz. cascade=persist ile ilişkilerde belirttiğiniz gibi, bir üyeyi ısrar ederken istemciler ve gruplar da kaydedilir. Yani, üyeler eklenirken gruplar güncellenir veya oluşturulur. Senin durumunda, bu mekanizma ile yeni bir grup yaratıyorsun. Yine de bu grup, label özellik kümesine sahip değildir, bu da veritabanında NULL değeriyle sonuçlanır ve bu, şema tarafından izin verilmez.

Dediğiniz gibi, bu hata zaten en iyi toplu iş sırasında ortaya çıkıyor. Çarpışmayı güncellediğiniz ilk 20 üyeden biri etiketsiz yeni bir grup oluşturur. Hangisinin olduğunu bulmak için, bir hata ayıklayıcısını kullanmanızı öneriyorum ve bu üyenin grubunun bir parçası olduğunu ve veritabanında var olduğunu görmek için her üyeyi devam ettirmeden önce denetleyin. Eğer mevcut değilse (ID ile), bu grubun neden gerekli etiket kümesi olmadığını araştırmalısınız.

Veritabanında aslında tüm gruplar var ise, işler biraz daha zorlaşır ve bu, güncelleştirmekte olduğunuz üyelerin nasıl yüklendiğine bağlıdır. EntityManager'dan (managed durumu) getirildiler mi veya farklı bir kaynaktan (örneğin serialized) ve dolayısıyla unmanaged durumunda mı yüklüler? Eğer yönetilemezlerse, onlar permanence üzerine yönetilecekler ve cascade=merge, müşteri ve grup ilişkisinin spesifikasyonuyla yönetilecekler. Burada bilmek önemli bir şey olsa da, merge yeni (yönetilen) bir varlık döndürecek ve daha sonra da kalıcı olacaktır (bkz. accepted answer here).Bu yeni bir nesne olduğu için, bu nesnenin tam olarak başlatılmadığı ve tanımlanmamış değerler içerebileceği ihtimali olabilir (daha sonra NULL'a çevirir). EntityManager farklı bir kaynaktan gelen member verileri yüklerken Yani, bu sorunu önlemek için ilk EntityManager ile bağlamak gerekebilir.

Sonuncusu hata ayıklamak oldukça zordur ve her bir varlığın gerçekte nasıl kalıcı olduğunu görmek için UnitOfWork->doPersist yöntemine başvurmanız gerekir.

+0

@ Fge, açık cevabınız için teşekkürler. Bu hata ilk ekleme/güncellemede görünür. ManyToOne 'Client :: $ group' ve' Member :: $ client' üzerindeki cascade = {"persist", "merge"}, bu davranışın nedeni olabilir. Toplu kaydetme yöntemi, "normal" kaydetme yönteminden gerçekten aynıdır. Tek fark, EntityManager'ın temizlenmesidir. Bu şekilde araştıracağım. Bu harika cevap için +1 – ceadreak