Symfony2条令试图插入记录两次?比赛条件?
我们在Symfony2中构建了一个调查构建应用程序(想想survey Monkey或Google表单)。当一名公众访问调查时,使用Symfony的Form Builder动态生成各种问题,并使用Doctrine保存其答案。目前,我们每天平均收集1000份完成的调查,没有任何问题,但是,我们时不时会收到一个Symfony2条令试图插入记录两次?比赛条件?,symfony,doctrine,Symfony,Doctrine,我们在Symfony2中构建了一个调查构建应用程序(想想survey Monkey或Google表单)。当一名公众访问调查时,使用Symfony的Form Builder动态生成各种问题,并使用Doctrine保存其答案。目前,我们每天平均收集1000份完成的调查,没有任何问题,但是,我们时不时会收到一个条令\DBAL例外 问题的每个答案都保存在一个表中,该表有一个唯一的键,由填写调查的人的ID和他们回答的问题的ID组成。有时,当条令试图插入他们的答案时,这个键被违反,查询失败。正如我提到的,这
条令\DBAL
例外
问题的每个答案都保存在一个表中,该表有一个唯一的键,由填写调查的人的ID和他们回答的问题的ID组成。有时,当条令试图插入他们的答案时,这个键被违反,查询失败。正如我提到的,这种情况很少发生,我们无法在测试环境中复制它
所有Symfony表单都是动态构建的,这使得事情变得更加复杂。下面是实际执行表单数据持久化的代码
public function save(\Symfony\Component\Form\Form $form, \Our\Namspace\Entity\Participant $participant)
{
/**
* $surveyReponse
*
* @var \Our\Namespace\Entity\SurveyResponse
*/
foreach ($form->getData() as $surveyResponseKey => $surveyResponse) {
$subQuestionId = $this->getQuestionIdFromSurveyResponseKey($surveyResponseKey);
$subQuestion = $this->getSubQuestionSettingsBySubQuestionId($subQuestionId);
if ($surveyResponse) {
$surveyResponse->setParticipant($participant)->setSubQuestion($subQuestion);
$participant->addResponse($surveyResponse);
$this->em->persist($surveyResponse);
}
$this->em->flush();
}
return true;
}
您可以看到,我们在表单数据中对问题(在我们的域中称为子问题)的ID进行编码,以获取(子)问题实体,然后在持久化之前在SurveyResponse对象上设置参与者和子问题$this->em只是条令实体管理器
如果没有看到所有的代码,可能任何人都很难弄清楚发生了什么,但是如果任何人过去有过类似的问题,也许他们可以提供一些建议
我们可以而且应该将persist和flush操作包装在try/catch块中,然后处理异常,但我们真的很想知道为什么会发生这种情况
SurveyResponse实体的相关位如下所示
class SurveyResponse implements SurveyAwareInterface
{
/**
* id of the response.
*
* @var int
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
protected $id;
/**
* the subQuestion to which the response refers.
*
* @var SurveySubQuestion
*
* @ORM\ManyToOne(targetEntity="\Our\Namspace\Entity\SurveySubQuestion", inversedBy="surveyResponses")
* @ORM\JoinColumn(name="sub_question_id", referencedColumnName="id")
*/
protected $subQuestion;
/**
* the participant.
*
* @var AbstractParticipant
*
* @ORM\ManyToOne(targetEntity="Our\Namespace\Entity\Participant", inversedBy="responses")
* @ORM\JoinColumn(name="participant_id", referencedColumnName="id", onDelete="CASCADE")
*/
protected $participant;
实体中有这个注释
* @ORM\Table(name="survey_response",
* uniqueConstraints= @ORM\UniqueConstraint(
* name="participant_response", columns={"participant_id", "sub_question_id"})})
*
注意:你不应该flush()
在foreach里面。@PawełMikołajczuk为什么不呢?因为当他知道要插入/更新的所有资源时,这是一项消耗资源的任务,而且条令更有效。对于许多插入,您可以使用批处理:是的,我们知道我们不应该在循环中刷新,但是除非我们这样做,否则将数据插入到数据库中不会正常工作。为什么它不起作用是另一个问题!