Doctrine2:多次调用 flush

Doctrine2: calling flush multiple times

我有一个关于 DoctrineSymfony 2.3.

上的实体的问题

根据v2.3《Documentation Book》章节《Databases and Doctrine》>Saving Related Entities,例子在 productcategory 表中同时创建一个新行,并将 product.category_id 值与新 类别 项目的 id 相关联。

问题是控制器操作会在调用时创建一个新的 Product 和一个新的 Category

为了只创建一个新的产品并将其category_id与现有的类别相关联id ,这是 routing.yml 路线:

acme_store_create_product_by_category:
path:     /create/newproduct/{name}/{categoryId}
defaults: { _controller: AcmeStoreBundle:Default:createProduct }

I made a test passing parameters via URL:
/web/store/create/newproduct/Kayak/12

我做了这样的事情,看起来工作正常:

public function createProductAction($name, $categoryId)
{
    $em = $this->getDoctrine()->getManager();

    if ( $em->getRepository("AcmeStoreBundle:Category")->findOneById($categoryId) ) {

        $product = new Product();

        $product->setName($name);
        $product->setPrice(220);
        $product->setDescription("This is just a test");

        $em->persist($product);

        $em->flush();

        $newproduct = $em->getRepository("AcmeStoreBundle:Product")->find($product->getId());
        /** Create new product and populate $newproduct with its data */


        $repository = $em->getRepository("AcmeStoreBundle:Category")->find($categoryId);

        $newproduct->setCategory($repository);

        $em->persist($newproduct);

        $em->flush();
        /** Update the id_category field of the new product with parameter $categoryId */

        //exit(\Doctrine\Common\Util\Debug::dump($product));

        return new Response('Create product ' . $name . ' with category id ' . $categoryId);

    } else {

        return new Response('It doesn\'t exists any category with id ' . $categoryId);
    }
}

我在这种情况下的疑问是:在同一个 action 中两次调用 flush() 方法是一个好习惯吗?在这种情况下,我想创建一个新的产品,从“列表框”中选择相关的类别

提前致谢!

我认为这主要取决于您的应用领域。如果您 运行 flush 两次,则表示您 运行 进行了两次交易。在第一个中,您要保留一个产品,在第二个中,您要保留一个类别。因此,如果第一笔交易失败(假设您在产品名称上有一个唯一键,并且您试图保留一个具有相同名称的产品,所以您会得到一个重复键异常)然后问问自己是否可以继续并坚持下去一个类别。我不认为我们可以在这里轻松回答这个问题,因为我认为这取决于您的应用程序逻辑、端点应该做什么、如果您最终拥有产品而不是类别会发生什么,反之亦然。

您还应该考虑到,如果您在第一次交易期间遇到异常,您的代码将不会处理该错误,因此第二次交易将失败。当像重复键这样的异常发生时,所有实体都被分离,实体管理器不再知道如何管理事物。所以你必须重置它,否则你会遇到 EntityManager is closed 问题。

try {
    // first transaction
    $entityManager->persist($entityOne);
    $entityManager->flush();
} catch (\Exception $e) {
    /* ... handle the exception */ 
    $entityManager->resetManager();
}

// now we can safely run a second transaction here

我希望这能回答您的问题:-)

我建议编辑后的代码片段。

    public function createProductAction($name, $categoryId)
    {
        $em = $this->getDoctrine()->getManager();
    
        if ( $em->getRepository("AcmeStoreBundle:Category")->findOneById($categoryId) ) {
    
            $repository = $em->getRepository("AcmeStoreBundle:Category")->find($categoryId);
    
            $product = new Product();
            $product->setName($name);
            $product->setPrice(220);
            $product->setDescription("This is just a test");
            $product->setCategory($repository);
    
            $em->persist($product);
            $em->flush();
    
            return new Response('Create product ' . $name . ' with category id ' . $categoryId);
    
        } else {
    
            return new Response('It doesn\'t exists any category with id ' . $categoryId);
        }
    }