2016-02-19 50 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