dream752614590 2017-10-07 06:41
浏览 687
已采纳

Laravel事务回滚似乎不起作用

I am running laravel 5.4 and noticed that rollbacks in transactions do not work. I set my database engine to InnoDB in the settings.php file and tried DB::rollback(); and DB::rollBack(); (i.e. upper and lower case b) but it does not roll back my database.

I wrote a unit test bellow. It creates a record, commits it, then rolls back. However, the last assertion fails. After it rolls back, the record is still found in the database. Is there something I am missing? Or is there a bug with laravel?

public function testRollback()
{
    $this->artisan('migrate:refresh', [
        '--seed' => '1'
    ]);

    DB::beginTransaction();

    Season::create(['start_date' => Carbon::now(), 'end_date' => Carbon::now(),]);
    DB::commit();
    $this->assertDatabaseHas('seasons', [
        'start_date' => Carbon::now(), 'end_date' => Carbon::now(),
    ]);

    DB::rollBack();
    // This assertion fails. It still finds the record after calling roll back
    $this->assertDatabaseMissing('seasons', [
        'start_date' => Carbon::now(), 'end_date' => Carbon::now(),
    ]);
}
  • 写回答

3条回答 默认 最新

  • doujuanju3076 2017-10-07 06:47
    关注

    The transaction consists of three steps:

    You start it with DB::beginTransaction or MySQL equivalent BEGIN TRANSACTION, then you execute the commands you need to and then (and here's the important part) you either COMMIT or ROLLBACK

    However once you've committed the transaction is done, you cant roll it back anymore.

    Change the test to:

    public function testRollback()
    {
        $this->artisan('migrate:refresh', [
            '--seed' => '1'
        ]);
    
        DB::beginTransaction();
    
        Season::create(['start_date' => Carbon::now(), 'end_date' => Carbon::now(),]);
    
        $this->assertDatabaseHas('seasons', [
            'start_date' => Carbon::now(), 'end_date' => Carbon::now(),
        ]);
    
        DB::rollback();
    
        $this->assertDatabaseMissing('seasons', [
            'start_date' => Carbon::now(), 'end_date' => Carbon::now(),
        ]);
    }
    

    This should work because until the transaction is rolled back the database "thinks" the record is in there.

    In practice when using transactions you want to use what's suggested in the docs, for example:

    DB::transaction(function()
    {
        DB::table('users')->update(array('votes' => 1));
    
        DB::table('posts')->delete();
    });
    

    This will ensure atomicity of wrapped operations and will rollback if an exception is thrown within the function body (which you can also throw yourself as a means to abort if you need to).

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?