一个多关系不一直与新实体 [英] OneToMany relationship not persisting along with new entities

查看:71
本文介绍了一个多关系不一直与新实体的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我尝试使用symfony表单来保存一组实体时,我正面临一些问题。我遵循了官方文档,但是我不能让它工作的错误:

 类型为ProductItem的实体通过
外部实体产品具有身份,但该实体没有身份本身。您必须在相关实体上调用
EntityManager#persist(),并确保在尝试保留ProductItem之前生成
标识符。在Post插入ID
生成(如MySQL自动增量或PostgreSQL SERIAL)的情况下,这意味着
必须在两个持久化操作之间调用EntityManager#flush()。

我必须连接到OneToMany关系的实体:



产品

  / ** 
* @ ORM\Column(name =id,type =integer,nullable = false
* @ ORM\Id
* @ ORM\GeneratedValue(strategy =IDENTITY)
* /
protected $ id;

/ **
* @ ORM\OneToMany(targetEntity =ProductItem,mappedBy =product,cascade = {persist})
* /
protected $ items;

And ProductItem

 code> / ** 
* @ ORM\Id()
* @ ORM\ManyToOne(targetEntity =Product,inversedBy =items)
* /
保护$产品;

/ **
* @ ORM\Id()
* @ ORM\ManyToOne(targetEntity =Item)
* /
受保护的$ item;

这是如何添加到窗体中的:

   - > add('items','collection',array(
'label'=> false,
'type'=>新的ProductItemType(),
'allow_add'=> true,
'allow_delete'=> true,
'by_reference'=> false))

这是控制器操作:

  public function newAction()
{
$ product = new Product();

$ form = $ this-> createForm(new ProductType(),$ product);
if($ request-> isMethod(POST))
{
$ form-> handleRequest($ request);
if($ form-> isValid())
{
$ em = $ this-> getDoctrine() - > getManager();
$ em-> persist($ product);
$ em-> flush();
}
}
}

我是在控制器中确实出错,因为正如错误消息所示,我必须在添加$ productItem之前坚持$ product,但我该怎么做?



我试图持久化一个新的实体时,只会收到此错误,如果实体已被持久化,我可以根据需要添加项目

解决方案

上周我有完全相同的问题,这是我在一些阅读和测试后发现的一个解决方案。



问题是您的产品实体具有级联持久性(通常很好),它首先尝试保留 ProductItem ProductItem 实体不能被持久化,因为它们要求产品首先被保留,并且它的ID(复合键(产品,项目))。



有两个选项可以解决这个问题: p>

1st 我没有使用它,但是ou可以简单地删除一个复合键,并使用外键的标准ID到 Product



2nd - 更好的这可能看起来像黑客,但相信我这是你现在可以做的最好的。它不需要对DB结构进行任何更改,并且与表单集合一起使用。没有任何问题。



代码片段从我的代码,文章部分有复合键(article_id, random_hash)。临时设置一个到许多引用一个空数组,坚持它,添加你原始数据并持续(和刷新)。

  if($ form-> isValid())
{
$ manager = $ this-> getDoctrine() - > getManager();

$ articleSections = $ article-> getArticleSections();
$ article-> setArticleSections(array()); //这不会触发级联持久化
$ manager-> persist($ article);
$ manager-> flush();

$ article-> setArticleSections($ articleSections);
$ manager-> persist($ article);
$ manager-> flush();


I'm facing some issue when I try to persist a collection of entities using a symfony form. I followed the official documentation but I can't make it work becouse of this error:

Entity of type ProductItem has identity through a
foreign entity Product, 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 ProductItem. 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.

I have to entities linked with a OneToMany relation:

Product

/**
 * @ORM\Column(name="id", type="integer", nullable=false)
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="IDENTITY")
 */
protected $id;

/**
 * @ORM\OneToMany(targetEntity="ProductItem", mappedBy="product",cascade={"persist"})
 */
protected $items;

And ProductItem

/**
 * @ORM\Id()
 * @ORM\ManyToOne(targetEntity="Product", inversedBy="items")
 */
protected $product;

/**
 * @ORM\Id()
 * @ORM\ManyToOne(targetEntity="Item")
 */
protected $item;

This is how it is added to the form:

->add('items','collection',array(
            'label' => false,
            'type' => new ProductItemType(),
            'allow_add' => true,
            'allow_delete' => true,
            'by_reference' => false))

And this is the controller action:

public function newAction()
{
    $product= new Product();

    $form = $this->createForm(new ProductType(), $product);
    if($request->isMethod("POST"))
    {
        $form->handleRequest($request);
        if($form->isValid())
        {
            $em = $this->getDoctrine()->getManager();
            $em->persist($product);
            $em->flush();
        }
    }
}

I'm doing something wrong for sure in the controller because, as the error message says, I have to persist $product before adding $productItems, but how can I do that?

I only get this error when trying to persist a new entity, if the entity has been persisted before, I can add as may items as I want successfully

解决方案

I had exact same problem last week, here is a solution I found after some reading and testing.

The problem is your Product entity has cascade persist (which is usually good) and it first try to persist ProductItem but ProductItem entities cannot be persisted because they require Product to be persisted first and its ID (Composite key (product, item).

There are 2 options to solve this:

1st I didn't use it but you could simply drop a composite key and use standard id with foreign key to the Product

2nd - better This might look like hack, but trust me this is the best what you can do now. It doesn't require any changes to the DB structure and works with form collections without any problems.

Code fragment from my code, article sections have composite key of (article_id, random_hash). Temporary set one to many reference to an empty array, persist it, add you original data and persist (and flush) again.

    if ($form->isValid())
    {
        $manager = $this->getDoctrine()->getManager();

        $articleSections = $article->getArticleSections();
        $article->setArticleSections(array());  // this won't trigger cascade persist
        $manager->persist($article);
        $manager->flush();

        $article->setArticleSections($articleSections);
        $manager->persist($article);
        $manager->flush();

这篇关于一个多关系不一直与新实体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆