Doctrine2:多次调用 flush
Doctrine2: calling flush multiple times
我有一个关于 Doctrine 和 Symfony 2.3.
上的实体的问题
根据v2.3《Documentation Book》章节《Databases and Doctrine》>Saving Related Entities,例子在 product
和 category
表中同时创建一个新行,并将 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);
}
}
我有一个关于 Doctrine 和 Symfony 2.3.
上的实体的问题根据v2.3《Documentation Book》章节《Databases and Doctrine》>Saving Related Entities,例子在 product
和 category
表中同时创建一个新行,并将 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);
}
}