Доктрина Symfony навальный вкладыш - PullRequest
0 голосов
/ 29 мая 2018

Я пытаюсь оптимизировать сохранение моей доктрины с помощью массовой вставки.Но во время сохранения я получаю следующую ошибку:

Новый объект был найден через отношение 'AppBundle \ Entity \ Product # category', который не был настроен для каскадных операций сохранения для объекта: AppBundle \ Entity\ Категория @ 00000000351492f00000000072328419.Чтобы решить эту проблему: либо явно вызовите EntityManager # persist () для этого неизвестного объекта, либо настройте каскадное сохранение этой ассоциации в сопоставлении, например @ManyToOne (.., cascade = {"persist"}).Если вы не можете выяснить, какая сущность вызывает проблему, реализуйте AppBundle \ Entity \ Category #__ toString (), чтобы получить подсказку.

Моя категория:

class Category
{

    /**
     * @var string
     *
     * @ORM\Id()
     * @ORM\Column(type="string", nullable=false, unique=true)
     * @ORM\GeneratedValue(strategy="UUID")
     */
    private $id;

    /**
     * @var Category
     * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Category", inversedBy="children")
     * @ORM\JoinColumn(name="parent_id", referencedColumnName="id", nullable=true)
     */
    private $parent;

    /**
     * @var ArrayCollection
     * @ORM\OneToMany(targetEntity="AppBundle\Entity\Category", mappedBy="parent", fetch="EAGER")
     */
    private $children;

    /**
     * @var ArrayCollection;
     * @ORM\OneToMany(targetEntity="AppBundle\Entity\Product", mappedBy="category", fetch="EAGER")
     */
    private $products;

    /**
     * @var string
     * @ORM\Column(type="string", nullable=false)
     */
    private $title;
}

Мой товар:

class Product
{

    /**
     * @ORM\Column(type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

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

    /**
     * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Category", inversedBy="products")
     * @ORM\JoinColumn(name="category_id", referencedColumnName="id", nullable=false)
     */
    protected $category;

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

}

Мой метод сохранения:

$em = $this->getDoctrine()->getManager();
$batchCount = 10;
for ($i = 0; $i < 10000; $i++) {
     $product = new Product();
     $product->setName("Product A");
     $product->setCategory("category A");
     $em->persist($product);
     if (($i % $batchCount) == 0) {
         $em->flush();
         $em->clear();
    }
}

1 Ответ

0 голосов
/ 29 мая 2018

Первое в вашем коде:

$product->setCategory("category A");

У вас не может быть этого, потому что для этого нужен объект, но я буду считать, что вы упростили свой код ради вопроса.

Вашпроблема заключается в том, что вы добавляете ассоциацию к продукту, но не добавляете ассоциацию к своей категории.

Обычно это имеет два решения:

// In your Product entity add cascade persist, this will check your categories as well and schedule them for persist during flush
/**
 * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Category", inversedBy="products", cascade={"persist"})
 * @ORM\JoinColumn(name="category_id", referencedColumnName="id", nullable=false)
 */
protected $category;

Следующее решение (я предпочитаю,потому что у вас есть все время контроль над всем).

// In your product entity set Category
public function setCategory(Category $category) {
    $this->category = $category;
    $category->addProduct($this);
}

// In you Category entity
public function addProduct(Product $product) {
    if (!$this->products->contains($product)) {
        $this->product->add($product);
    }
}

Вы можете использовать оба одновременно.

...