我正在尝试遍历一些实体并更新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);
}
在步骤回购内
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;
}
我期望发生的事情如下:
- 选择最大值(step_order(
- 开始交易
- 更新每个实体的step_order
- 运行查询更新所有step_orders = step_order - MAX(step_order(
- 犯
发生了什么事情:
- 选择最大值(step_order(
- 开始交易
- 运行查询更新所有step_orders = step_order - MAX(step_order(
- 犯
以下是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]:nnSQLSTATE[22003]: Numeric value out of range: 1690 BIGINT UNSIGNED value is out of range in '(`toolbox`.`lsp_maintenance_step`.`step_order` - 4)'
错误是正确的,因为从任何实体中减去 4 将使步长顺序保持在 0 或更小,这是不正确的。
为什么教义在更新实体之前运行最后UPDATE
?
为什么在更新实体之前,学说运行最后一个
UPDATE
?
经过一些挖掘,我发现当EntityManager
上调用flush()
时,实体会提交,而execute()
会立即运行。
为了解决这个问题,我使用了事务嵌套,其中实体在子事务中提交,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();
}