我有以下代码:
$em = $this->getDoctrine()->getManager();
$evaluation->getQuestions()->clear();
foreach ($questions_data as $data) {
$id = (int) $data['id'];
if ($id > 0) {
$question = $em->getRepository('MyBundle:Question')->find($id);
if ($question)
$evaluation->getQuestions()->add($question);
}
}
$em->persist($evaluation);
$em->flush();
以下是$questions_data
- array(['id' => 2], ['id' => 1], ['id' => 3])
以下是教义如何将问题持续存在于数据库中:
那么,如何让学说不对问题进行排序呢?
Evaluation
实体与ManyToMany
实体有Question
关系,因此ORDER BY
无法提供帮助,因为evaluations_questions
表自动创建了表Doctrine
,没有字段id
。
答案 0 :(得分:5)
当您在Doctrine中刷新新持久化的项目时,Doctrine必须使用内部函数getCommitOrder
确定将它们提交到数据库的顺序。该函数的目的是确保在提交对象之前提交对象的依赖性。这样做是为了符合可能设置的任何外键约束。正如您所观察到的那样,对数据进行排序的结果就是您失去了精确调整项目提交顺序的能力 - 这不一定是坏事。
在SQL中,您可以通过ORDER BY
发出查询来查看结果的唯一方法。如果您选择不指定排序方法,则不能指望结果以任何特定顺序返回。 PostgreSQL docs解释了这个:
如果未选择排序,则将以未指定的顺序返回行。在这种情况下,实际订单将取决于扫描和加入计划类型以及磁盘上的订单,但不能依赖。
换句话说,内容存储在数据库中的顺序并不重要。
在您的问题中,问题对用户的显示顺序是个问题。您不能允许问题在评估中随机出现 - 它们必须遵循预设的顺序。 Frankbeen在评论中对此进行了讨论,但最好的解决方案是在Evaluation
上添加一个新字段,以适当的顺序存储Questions
$em = $this->getDoctrine()->getManager();
$evaluation->getQuestions()->clear();
foreach ($questions_data as $data) {
$id = (int) $data['id'];
if ($id > 0) {
$question = $em->getRepository('MyBundle:Question')->find($id);
if ($question) {
$evaluation->getQuestions()->add($question);
$em->persist($evaluation);
$em->flush();
}
}
}
。然后,当您向用户提供评估时,可以阅读订单。
如果您绝对必须按照数据库中的特定顺序对它们进行排序,那么您应该能够在持久化时单独刷新新对象,而不是将它们安排为一起刷新。
TableA {
String aId;
@OneToMany(fetch = FetchType.EAGER)
List<TableB> tableB;
}
TableB {
String aId;
String bId;
@ManyToOne(fetch = FetchType.EAGER)
TableC tableC;
}
TableC {
String cId;
String name;
}
请注意,这将需要更长的时间才能完成,对您的问题来说是一个非常糟糕的解决方案。
答案 1 :(得分:1)
新记录始终存储在表的末尾。如果您想以自然顺序(通过id)获得问题,那么您应该使用ORDER BY。我猜评价实体与问题实体有一个OneToMany关系。
在这种情况下,您可以在Evalutation实体的$ questions属性上方添加可选注释:
/**
* @ORM\OneToMany(targetEntity="Question")
* @ORM\OrderBy({"id" = "ASC"})
*/
private $questions;
答案 2 :(得分:0)
EntityManagerInterface
具有事务支持,我建议对所有多语句操作使用该功能。这将允许您创建多个语句,并一次按顺序提交它们。每条语句将按照添加的顺序执行,如果一条语句失败,则完全不会对数据库进行任何更改。
话虽这么说,所有数据库实现都可能未按添加顺序存储数据,因此,如果期望按特定顺序返回数据,则应始终使用ORDER BY
进行显式查询,如另一个回复。
如果遇到ID不明的问题,说要中止操作。可以使用以下类似的方法很容易地完成此操作:
function storeQuestions($questions_data): bool
{
$em = $this->getDoctrine()->getManager();
$em->beginTransaction();
$evaluation->getQuestions()->clear();
foreach ($questions_data as $data) {
$id = (int) $data['id'];
if ($id > 0) {
$question = $em->getRepository('MyBundle:Question')->find($id);
if ($question) {
$evaluation->getQuestions()->add($question);
$em->persist($evaluation);
} else {
$em->rollback();
return false;
}
}
}
$em->commit();
$em->flush();
return true; // Success
}