2017-08-17 5 views
1

一部のエンティティをループしてstep_order列を更新しようとしていて、その列から値を減算しようとしています。以下の例を見てみましょう:これらのエンティティとトランザクション中にエンティティに影響を与えるクエリを実行する方法

  1. スタート

    ID | step_order 
    1 | 1 
    2 | 2 
    3 | 3 
    4 | 4 
    
  2. 変更オーダー

    ID | step_order 
    1 | 6 
    2 | 5 
    3 | 7 
    4 | 8 
    
  3. 減算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; 
} 

以内に私が起こることを期待以下の通りです:

  1. MAXを選択(step_order)
  2. すべてstep_ordersを更新し、各エンティティ
  3. 実行クエリの
  4. スタートトランザクション
  5. 更新step_order = step_order - MAX(step_order)
  6. は何が起こっている

をコミット:

  1. セレクトMAX (step_order)
  2. トランザクション開始
  3. すべてstep_ordersを更新
  4. 実行クエリは= step_order - MAX(step_order)
  5. はここ

をコミット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に呼び出されたときに実体がコミットされていることを発見したいくつかの掘削後

答えて

1

Why is doctrine running the last UPDATE before updating the entities?

私は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(); 
} 
+0

「persist」はクエリをキューに入れるだけです。 'flush'は実際にバッチを実行します。したがって、エンティティを変更して 'persist'を呼び出す間に、' flush'を呼び出すときに最後の変更だけが有効になります。 – tlorens

関連する問題