2017-08-17 60 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. 开始交易
  3. 为每个实体
  4. 更新step_order
  5. 运行查询更新所有step_orders = step_order - MAX(step_order)
  6. 提交

正在发生的事情:

  1. 选择MAX (step_order)
  2. 开始交易
  3. 运行查询更新所有step_orders = step_order - MAX(step_order)
  4. 提交

这里是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或更小,这是不正确的。

为什么在更新实体之前运行最后的UPDATE原则?

回答

1

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

一些挖后,我发现,实体都致力于在flush()被呼吁EntityManager而​​立即跑了。

为了解决这个问题,我使用了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

相关问题