2016-02-19 52 views
3

我有多个类方法,每个方法在引发异常时都使用事务和回滚。下面的基本示例。包装使用事务的类方法

class TaskMapper 
{ 
    private $dblayer; 

    public function __construct(PDO $dblayer) 
    { 
     $this->dblayer = $dblayer; 
    } 

    public function save(Task $task) 
    { 
     try { 
      $this->dblayer->beginTransaction(); 

      $stmt = ... // query/queries here 
      $stmt->execute(); 

      $stmt2 = ... // query/queries here 
      $stmt2->execute(); 

      $this->dblayer->commit(); 

     } catch (\PDOException $e) { 

      $this->dblayer->rollBack(); 
      // deal with exception here 
     } 


    } 

    public function editField($id, $field, $value) 
    { 
     try { 
      $this->dblayer->beginTransaction(); 

      $stmt = ... // query/queries here 
      $stmt->execute(); 

      $stmt2 = ... // query/queries here 
      $stmt2->execute(); 

      $stmt->execute(); 

      $this->dblayer->commit(); 

     } catch (\PDOException $e) { 

      $this->dblayer->rollBack(); 
      // deal with exception here 
     } 
    } 

} 

现在,我写它利用包含类似于上述代码中的多个类方法cron作业的脚本 - 与交易和回滚和异常。

例如:

if (date('j') == '1') { 
    // reset monthly count column 
    $task->editField(17, 'monthly_count', '0'); 
} 
$task->save($task); 

这是一个非常剥去例子,但我想知道是否有可能来包装一个try/catch块中的单个事务中的所有方法的调用,在捕获中回滚?因此,将上面的代码封装在一个try/catch中,并在catch中使用事务和回滚?

如果不是,处理这种情况的最好方法是如果一个方法调用失败,其他方法必须回滚。

在此先感谢。

+0

对于我来说,save()方法的存在意味着所有数据库事务都将从该调用中处理。到那时为止,变化只在php对象级别完成。 save()的作用是保持更改并因此将所有查询包装到单个事务中。 – Shadow

回答

0

我从来没有使用过它,但有一个PDO::inTransaction方法,您可以使用它来查看是否有更高级别的事务已启动。

所以,你可以换到

if (!$this->dblayer->inTransaction()) { 
    $this->dblayer->beginTransaction(); 
} 

,并因此对提交为好。

这将让您决定是否使用“本地”事务,从而可以使用“全局”事务将所有这些方法包装在一起。

+0

这不会是一个坏主意,但是,在OP中没有任何迹象表明任务会启动并且保持全面的事务处于打开状态。因此inTransaction()会返回false。 – Shadow

+0

@Shadow你能解释一下你的意思吗 - 关于保持交易公开?谢谢 – DJC

+0

如果存在打开的事务,则inTransaction()返回true。但是,save()和editField()方法都有自己的启动事务和提交。如果您在调用start()或editField()之前启动数据库事务**,那么在Transaction()方法中唯一的方法是有用的。 – Shadow

1

我宁愿添加一个答案,因为评论太短而无法解释。

基本上,您有两种方法可以在应用程序的单个事务中处理多个操作。

  1. 调用启动事务的方法。每个后续的方法调用时,属性更改都会导致数据库发生更改。这些操作中的任何错误都会导致回滚。最后你调用另一个提交整个事务的方法。

  2. 每一个方法调用,属性改变只会改变php对象的状态,所以数据库不会改变。在对所有更改满意之后,您会调用一种方法,该操作会持续对数据库进行所有更改。回调/提交也在这个调用中执行。

MySQL不支持嵌套事务,所以无论使用第一种方法结合PDO:inTransaction如@YourCommonSense还通过发起交易建议主叫EDITFIELD()之前,或者必须取出数据库修改代码从editField()和类似的调用中只使用save()。

+0

感谢你 - 将尝试这些并标记为正确的,但可能有更多的问题! – DJC