一部のエンティティをループして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;
}
以内に私が起こることを期待以下の通りです:
- MAXを選択(step_order) すべてstep_ordersを更新し、各エンティティ
- 実行クエリの
- スタートトランザクション
- 更新step_order = step_order - MAX(step_order)
- は何が起こっている
をコミット:
- セレクトMAX (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]:\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
を実行しているのはなぜですか?私はがすぐに実行されるのに対し、flush()
がEntityManager
に呼び出されたときに実体がコミットされていることを発見したいくつかの掘削後
「persist」はクエリをキューに入れるだけです。 'flush'は実際にバッチを実行します。したがって、エンティティを変更して 'persist'を呼び出す間に、' flush'を呼び出すときに最後の変更だけが有効になります。 – tlorens