我正在尝试遍历某些实体并更新step_order
列,然后从该列中减去一个值。请看以下示例:
从这些实体开始
ID | step_order
1 | 1
2 | 2
3 | 3
4 | 4
更改订单
ID | step_order
1 | 6
2 | 5
3 | 7
4 | 8
从订单中减去4,将值恢复为1
ID | step_order
1 | 2
2 | 1
3 | 3
4 | 4
这是我删除了无关部分的代码:
在经理
中$nextOrder = $this->stepRepo->findNextOrder($maintenanceId);
$steps = [];
foreach ($order as $o => $stepId) {
$step = $this->getStep($stepId);
$steps[] = $step;
}
$this->em->beginTransaction();
foreach ($steps as $o => $step) {
$step->setStepOrder($nextOrder + $o);
$this->em->persist($step);
}
$this->stepRepo->subtractOrder($maintenanceId, $nextOrder - 1);
$this->em->commit();
$this->em->flush();
public function getStep($id)
{
return $this->stepRepo->find($id);
}
在stepRepo中
public function subtractOrder($maintenanceId, $amount)
{
$maintenanceId = (int) $maintenanceId;
$qb = $this->createQueryBuilder('s');
$qb->update()
->set('s.stepOrder', 's.stepOrder - :amount')
->where('s.maintenanceId = :maintenanceId')
->setParameter('amount', $amount)
->setParameter('maintenanceId', $maintenanceId);
$result = $qb->getQuery()->execute();
return $result;
}
我期望发生的事情如下:
发生了什么:
以下是symfony探查器的输出:
SELECT MAX(l0_.step_order) AS sclr_0 FROM lsp_maintenance_step l0_ WHERE l0_.maintenance_id = ?
Parameters: ['1']
"START TRANSACTION"
Parameters: { }
UPDATE lsp_maintenance_step SET step_order = step_order - ? WHERE maintenance_id = ?
Parameters: [4, 1]
这是MySQL错误:
An exception occurred while executing 'UPDATE lsp_maintenance_step SET step_order = step_order - ? WHERE maintenance_id = ?' with params [4, 1]:\n\nSQLSTATE[22003]: Numeric value out of range: 1690 BIGINT UNSIGNED value is out of range in '(`toolbox`.`lsp_maintenance_step`.`step_order` - 4)'
错误是正确的,因为从任何实体中减去4会使步骤顺序为0或更小,这是不正确的。
为什么在更新实体之前,doctrine会运行最后一个UPDATE
?
答案 0 :(得分:1)
为什么在更新实体之前,doctrine会运行最后一个
UPDATE
?
经过一番挖掘后,我发现在flush()
上调用EntityManager
时会提交实体,而execute()
会立即运行。
为了解决这个问题,我使用transaction nesting,其中实体在子事务中提交,并且在主事务中调用UPDATE
。
$this->em->beginTransaction();
try {
$this->em->beginTransaction();
try {
foreach ($steps as $o => $step) {
$step->setStepOrder($nextOrder + $o);
$this->em->persist($step);
}
$this->em->flush();
} catch (\Exception $e) {
$this->em->rollback();
throw $e;
}
$this->stepRepo->subtractOrder($maintenanceId, $nextOrder - 1);
$this->em->flush();
foreach ($steps as $step) {
$this->em->refresh($step);
}
} catch (\Exception $e) {
$this->em->rollback();
}