我猜这是一个Doctrine错误(我已经在JIRA问题跟踪器上提交了一个问题),但如果这只是用户错误,我决定在这里发布它。
概要
在具有Composite Primary的联接表中持久化实体集合由2个外键和一个元数据字段组成的密钥在某些情况下会失败。代码基于此处的说明:条令文档
问题详细信息
-
成功:当FOREIGN KEY 1在要持久化的集合中的项之间相同时,并且在任何现有的PRIMARY KEY中,FOREIGN KEY 2大于FOREIGN KEY2并且集合中的相关实体被正确地持久化:
-
示例:GPA"add-val below"存在并且具有评估值
{"assessment":6,"value":4}
我们将尝试添加一个新的评估值,其中assessment_id>任何现有的评估值GPA的评估值"在下加一个值"> -
请求有效载荷:
{"name":"add val below","courses":[],"assessmentValues":[{"assessment":6,"value":4},{"assessment":7,"value":3}]}
-
调试日志:
〔2013-12-31 11:48:48〕应用程序。INFO:GPA ID在控制器中预售:9[][]〔2013-12-31 11:48:48〕应用程序。信息:预测在控制器评估VAL评估ID:7[][]〔2013-12-31 11:48:48〕应用程序。信息:预测在控制器评估价值点:3[][]〔2013-12-31 11:48:48〕应用程序。INFO:GPA ID在控制器中预售:9[][]〔2013-12-31 11:48:48〕应用程序。信息:预测在控制器评估VAL评估ID:6[][]〔2013-12-31 11:48:48〕应用程序。信息:预测在控制器评估价值点:4[][]〔2013-12-31 11:48:48〕学说。DEBUG:"启动事务"[][]〔2013-12-31 11:48:48〕学说。调试:插入gpa_aassessment_value(point_value,grade_point_average_id,assessment_id)值(?,?,?){"1":3,"2":"9","3":"7"}[]〔2013-12-31 11:48:48〕学说。调试:更新gpa_aassessment_value设置点_value=?其中grade_point_average_id=?AND assessment_id=?[4,9,6][]〔2013-12-31 11:48:48〕学说。调试:"COMMIT"[][]
-
-
失败:当FOREIGN KEY 1在集合中的所有项中都相同,并且FOREIGN KEY2小于任何现有的FOREIGN KEY 2时,工作单元将尝试插入现有实体,而不对新实体进行操作。
-
示例:GPA"add-val above"存在并且具有评估值
{"assessment":8,"value":2}
我们将尝试添加新的评估值,其中assessment_id<任何现有的GPA的评估值"加上val以上"> -
请求有效载荷:
{"name":"add val above","courses":[],"assessmentValues":[{"assessment":6,"value":4},{"assessment":8,"value":2}]}
-
调试日志:
〔2013-12-31 11:53:59〕应用程序。INFO:GPA ID在控制器中预售:10[][]〔2013-12-31 11:53:59〕应用程序。信息:预测在控制器评估VAL评估ID:8[][]〔2013-12-31 11:53:59〕应用程序。信息:预测控制器评估值点数:2[][]〔2013-12-31 11:53:59〕应用程序。INFO:GPA ID在控制器中预售:10[][]〔2013-12-31 11:53:59〕应用程序。信息:预测在控制器评估VAL评估ID:6[][]〔2013-12-31 11:53:59〕应用程序。信息:预测在控制器评估价值点:4[][]〔2013-12-31 11:53:59〕学说。DEBUG:"启动事务"[][]〔2013-12-31 11:53:59〕学说。调试:插入gpa_aassessment_value(point_value,grade_point_average_id,assessment_id)值(?,?,?){"1":2,"2":"10","3":"8"}[]〔2013-12-31 11:53:59〕学说。DEBUG:"回滚"[][]〔2013-12-31 11:53:59〕请求。关键:未捕获的PHP异常原则\DBAL\DALException:"使用参数[2,"10","8"]执行'INSERT INTO gpa_aassessment_value(point_value,grade_point_average_id,assessment_id)VALUES(?,?,?)'时发生异常:SQLSTATE[23505]:唯一冲突:7错误:重复的键值违反了唯一约束"gpa_aassessment_value_pkey">
-
代码
migration.sql
CREATE TABLE评估(id bigserial NOT NULL,scale_ id bigint NOT NULL,title varchar NOT NULL,传递布尔值NOT NULL,秩int,主键(id));创建表格评估_刻度(id bigserial NOT NULL,name varchar NOT NULL,主键(id));--。。。创建表格grade_point_average(id bigserial NOT NULL,name varchar NOT NULL,additional_credit_allowance数字(4,2),主键(id));--。。。创建表gpa_aassessment_value(grade_point_average_id bigint NOT NULL,assessment_id bigint NOT NULL,point_value numeric(4,2)NOT NULL,PRIMARY KEY(assessment_id,grade_point_average_id),外国密钥(assessment_id)参考文献评估,外键(grade_point_average_id)参考grade_point_average)
模型/坡度点平均值.php
命名空间MyApp\Model;使用条令\ORM\映射\实体;使用条令\ORM\映射\Id;使用条令\ORM\映射\GeneratedValue;使用条令\ORM\Mapping\Column;//。。。使用条令\Common\Collections\Collection;使用条令\Common\Collections\ArrayCollection;使用MyApp\Util\CConstructorArgs;使用MyApp\Model\GradePointAverage\AssementValue;//。。。/***@Entity("MyApp\Repository\GradePointAverageRepository")*/类GradePointAverage{使用ConstructorArgs;/***@Id*@GeneratedValue*@Column(type="bigint")**@var int*/私人$id;//。。。/***@OneToMany(targetEntity="MyApp\Model\GradePointAverage\AssistanmentValue",mappedBy="GradePointAverage",cascade="persistent")**@var集合*/私人$assessmentValues;//。。。/***@param数组$args*/公共函数__construct(数组$args=[]){$this->assessmentValues=new ArrayCollection;//。。。$this->handleArgs($args);}//。。。/***@return集合*/公共函数getAssessmentValues(){return$this->assessmentValues;}/***@param ArrayCollection$assessmentValues*/公共函数setAssessmentValues(ArrayCollection$assessmentValues){$this->assessmentValues=$assessmentValues;}/***@param评估值$AssessmentValue*/公共函数addAssessmentValue(AssessmentValue$AssessmentValue){$this->assessmentValues->add($assessmentValue);}/***@param评估值$AssessmentValue*/公共函数removeAssementValue(AssessmentValue$AssessmentValue){$this->assessmentValues->removeElement($assessmentValue);}//。。。}
模型/绩点平均值/评估值.php
命名空间MyApp\Model\GradePointAverage;使用条令\ORM\映射\实体;使用条令\ORM\Mapping\Table;使用条令\ORM\Mapping\Column;使用条令\ORM\映射\Id;使用条令\ORM\映射\GeneratedValue;使用条令\ORM\Mapping\ManyToOne;使用条令\ORM\映射\JoinColumn;使用MyApp\Model\GradePointAverage;使用MyApp \模型\评估;使用MyApp\Util\CConstructorArgs;/***@Entity("MyApp\Repository\GradePointAverage\AssistanmentValueRepository")*@表格("gpa_aassessment_value")*/类别评估值{使用ConstructorArgs;/***@Id*@ManyToOne(targetEntity="MyApp\Model\GradePointAverage")*/private$gradePointAverage;/***@Id*@ManyToOne(targetEntity="MyApp \模型\评估")*/私人美元评估;/***@列("point_value")**@var浮动*/私人美元价值;/***@param数组$args*/公共函数__construct(数组$args=[]){$this->handleArgs($args);}/***@return GradePointAverage*/公共函数getGradePointAverage(){return$this->gradePointAverage;}/***@param GradePointAverage$gradePointAverive*/公共函数setGradePointAverage(GradePointAverage$gradePointAverive){$this->gradePointAverage=$gradePointAverage;}/***@return评估*/公共函数getAssessment(){return$this->评估;}/***@param评估$Assessment*/公共功能集评估(评估$Assessment){$this->assessment=$assessment;}/***@回流浮子*/公共函数getValue(){返回$this->值;}/***@param float$value*/公共函数setValue($value){$this->value=$value;}/***@return评估量表*/公共函数getAssessmentScale(){return$this->assessment->getScale();}}
模型/评估.php
命名空间MyApp\Model;使用条令\ORM\映射\实体;使用条令\ORM\映射\Id;使用条令\ORM\映射\GeneratedValue;使用条令\ORM\Mapping\Column;使用条令\ORM\Mapping\ManyToOne;使用MyApp \模型\评估\量表;使用MyApp\Util\CConstructorArgs;/***@Entity("MyApp\Repository\AssistanmentRepository")*/班级评估{使用ConstructorArgs;/***@Id*@GeneratedValue*@Column(type="bigint")**@var int*/私人$id;//。。。/***@param数组$args*/公共函数__construct(数组$args=[]){$this->handleArgs($args);}/***@return int*/公共函数getId(){return$this->id;}//。。。}
存储库/GradePointAverageRepository.php
命名空间MyApp\Repository;使用条令\ORM\EntityRepository;//。。。使用MyApp\Model\GradePointAverage;类GradePointAverageRepository扩展BaseRepository实现GradePointEverageRepositoryInterface{//。。。/***@param GradePointAverage$gradePointAverive*/公共函数保存(GradePointAverage$GradePointAverage){$this->getEntityManager()->persistent($gradePointAverage);$this->getEntityManager()->flush();}}
存储库/成绩点平均值/评估值存储库.php
命名空间MyApp\Repository\GradePointAverage;使用条令\ORM\EntityRepository;使用MyApp\Model\GradePointAverage\AssementValue;类AssessmentValueRepository扩展EntityRepository{/***@param评估值$AssessmentValue*/公共函数保存(AssessmentValue$AssessmentValue){$this->getEntityManager()->persistent($assessmentValue);$this->getEntityManager()->flush();}}
经理/GradePointAverageManager.php
命名空间MyApp\Manager;使用InvalidArgumentException;使用Symfony\Component\Validator\ValidatorInterface;使用JMS\DiExtraBundle\Annotation\Service;使用JMS\DiExtraBundle\Annotation\InjectParams;使用JMS\SecurityExtraBundle\Annotation\PreAuthorize;使用Knp\Component\Pager\Pagination\PaginationInterface;使用MyApp\Repository\GradePointAverageRepository;使用MyApp\PaginationFactory\GradePointAveragePaginationFactoryInterface;使用MyApp\Model\GradePointAverage;/***@Service("grade_point_average_manager")*/class GradePointAverageManager{/***@var GradePointAverageRepository*/私有$gradePointAverageRepository;/***@var GradePointAveragePaginationFactoryInterface*/private$gradePointAveragePaginationFactory;/***@var验证器接口*/私人$验证器;/***@InjectParams**@param GradePointAverageRepository$gradePointAverage Repository*@param GradePointAveragePaginationFactoryInterface$gradePointAverage PaginationFactory*@param ValidatorInterface$validator*/公共函数__construct(GradePointAverageRepository$gradePointAverage Repository,GradePointAveragePaginationFactoryInterface$gradePointAverage PaginationFactory,ValidatorInterface$validator){$this->gradePointAverageRepository=$gradePointEverageRepository;$this->gradePointAveragePaginationFactory=$gradePointEveragePagination Factory;$this->validator=$validator;}/***@PreAuthorize("isAllowedToManageTheGradePointAverage(#gradePointAverive)")*@param GradePointAverage$gradePointAverive*@throws InvalidArgumentException*/公共函数保存(GradePointAverage$GradePointAverage){$violationList=$this->validator->validate($gradePointAverage);if($violationList->count()){抛出新的InvalidArgumentException;}$this->gradePointAverageRepository->save($gradePointAverage);}}
控制器/GradePointAverageController.php
命名空间MyApp\Controller;使用Symfony\Component\HttpFoundation\Request;使用Symfony\Component\HttpFoundation\Response;使用Symfony\Component\HttpKernel\Log\LoggerInterface;使用Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;使用Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;使用条令\Common\Collections\ArrayCollection;使用FOS\RestBundle\View\View;使用JMS\DiExtraBundle\Annotation\Service;使用JMS\DiExtraBundle\Annotation\InjectParams;使用JMS\SecurityExtraBundle\Annotation\PreAuthorize;使用Knp\Component\Pager\Pagination\PaginationInterface;使用MyApp\Manager\GradePointAverageManager;使用MyApp\Model\GradePointAverage;使用MyApp\Model\GradePointAverage\AssementValue;/***@Service("grade_point_average_controller",parent="app.controller.abstract")*@路由("/gpa",service="grade_point_average_controller")*/类GradePointAverageController扩展BaseController{/***@var GradePointAverageManager*/private$gradePointAverageManager;私人$logger;/***@InjectParams**@param GradePointAverageManager$gradePointAverage Manager*@param LoggerInterface$logger*/公共函数__construct(GradePointAverageManager$gradePointAverage Manager,LoggerInterface$logger){$this->gradePointAverageManager=$gradePointEverageManager;$this->logger=$logger;}//。。。/***@Route("/{id}",name="gpa.edit",requirements={"id"="\d+"})*@方法("PUT")**@param请求$Request*@param GradePointAverage$gpa*@return视图*/公共函数editAction(请求$Request,GradePointAverage$gpa){$form=$this->formFactory->createNamed(null,'gpa',$gpa['method'=>'PUT',]);$form->handleRequest($request);foreach($gpa->getAssessmentValues()为$av){$this->logger->info('GPA ID PREVALIDATE IN CONTROLLER:'.$GPA->getId());$this->logger->info('PREVALIDATE IN CONTROLLER ASSESSMENT VAL ASSESSMENT ID:'.$av->getAssessment()->getId());$this->logger->info('PREVALIDATE IN CONTROLLER ASSESSMENT VALPOINTS:'.$av->getValue());}/*//试着颠倒集合的顺序,看看这是否有帮助$assessmentVals=$gpa->getAssessmentValues()->toArray();$reversed=array_reverse($assessmentVals);$reversedRoll=新的ArrayCollection($reversed);$gpa->setAssessmentValues($reversedRoll);*/if($form->isValid()){foreach($gpa->getAssessmentValues()为$av){$this->logger->info('GPA ID PRESAVE IN CONTROLLER:'.$GPA->getId());$this->logger->info('PREAVE IN CONTROLLER ASSESSMENT VAL ASSESSMENT ID:'.$av->getAssessment()->getId());$this->logger->info('PREAVE IN CONTROLLER ASSESSMENT VALPOINTS:'.$av->getValue());}$this->gradePointAverageManager->save($gpa);返回新视图($gpa204);}返回新视图($form);}//。。。}
尝试向表gpa_aassessment_value添加一个Id,然后使用命令行生成实体。如果不添加id字段,则从数据库映射orm文件将不会创建gpa_aassessment_value.org.myml。
CREATE TABLE gpa_assessment_value
(
id bigserial NOT NULL,
grade_point_average_id bigint NOT NULL,
assessment_id bigint NOT NULL,
point_value numeric(4, 2) NOT NULL,
PRIMARY KEY (id,assessment_id, grade_point_average_id),
FOREIGN KEY (assessment_id) REFERENCES assessment,
FOREIGN KEY (grade_point_average_id) REFERENCES grade_point_average
);