口若悬河的 ORM 交易

Eloquent ORM 相当不错,不过我想知道是否有一种简单的方法可以使用 innoDB 以与 PDO 相同的方式来设置 MySQL 事务,或者我是否需要扩展 ORM 来实现这一点?

138659 次浏览

你可以这样做:

DB::transaction(function() {
//
});

闭包中的所有内容都在事务中执行。如果发生异常,它将自动回滚。

如果你不喜欢匿名函数:

try {
DB::connection()->pdo->beginTransaction();
// database queries here
DB::connection()->pdo->commit();
} catch (\PDOException $e) {
// Woopsy
DB::connection()->pdo->rollBack();
}

更新 : 对于 laravel 4,pdo对象不再是公共的,所以:

try {
DB::beginTransaction();
// database queries here
DB::commit();
} catch (\PDOException $e) {
// Woopsy
DB::rollBack();
}

如果你想使用雄辩,你也可以使用这个

这只是我项目中的示例代码

        /*
* Saving Question
*/
$question = new Question;
$questionCategory = new QuestionCategory;


/*
* Insert new record for question
*/
$question->title = $title;
$question->user_id = Auth::user()->user_id;
$question->description = $description;
$question->time_post = date('Y-m-d H:i:s');


if(Input::has('expiredtime'))
$question->expired_time = Input::get('expiredtime');


$questionCategory->category_id = $category;
$questionCategory->time_added = date('Y-m-d H:i:s');


DB::transaction(function() use ($question, $questionCategory) {


$question->save();


/*
* insert new record for question category
*/
$questionCategory->question_id = $question->id;
$questionCategory->save();
});

由于某种原因,在任何地方都很难找到这个信息,所以我决定把它贴在这里,因为我的问题,虽然与雄辩的交易有关,但正是改变了这一点。

在阅读了 这个堆栈溢出的答案后,我意识到我的数据库表正在使用 MyISAM 而不是 InnoDB。

为了让事务在 Laravel (或任何其他地方)上工作,需要将表设置为使用 InnoDB

为什么?

引用 MySQL交易和原子业务文档(给你) :

MySQL Server (版本3.23-max 和所有版本4.0及以上)支持带有 InnoDB 和 BDB 事务性存储引擎的事务。InnoDB 提供了完全的 ACID 遵从性。见第14章,存储引擎。有关 InnoDB 在处理事务错误方面与标准 SQL 不同的信息,请参见第14.2.11节“ InnoDB 错误处理”。

MySQLServer 中的其他非事务性存储引擎(如 MyISAM)遵循不同的数据完整性范例,称为“原子操作”在事务方面,MyISAM 表有效地总是在 autocommit = 1模式下运行。原子操作通常提供相当的完整性和更高的性能。

因为 MySQLServer 支持这两种范例,所以您可以决定应用程序的最佳服务是原子操作的速度还是事务特性的使用。这个选择可以在每个表的基础上进行。

If you want to avoid closures, and happy to use facades, the following keeps things nice and clean:

try {
\DB::beginTransaction();


$user = \Auth::user();
$user->fill($request->all());
$user->push();


\DB::commit();


} catch (Throwable $e) {
\DB::rollback();
}

如果任何语句失败,则永远不会执行提交,事务也不会处理。

我肯定你不是在寻找一个封闭的解决方案,试试这个更紧凑的解决方案

 try{
DB::beginTransaction();


/*
* Your DB code
* */


DB::commit();
}catch(\Exception $e){
DB::rollback();
}

如果发生任何异常,事务将自动回滚。

Laravel Basic transaction format

    try{
DB::beginTransaction();


/*
* SQL operation one
* SQL operation two
..................
..................
* SQL operation n */




DB::commit();
/* Transaction successful. */
}catch(\Exception $e){


DB::rollback();
/* Transaction failed. */
}

最好和明确的方法:

DB::beginTransaction();


try {
DB::insert(...);
DB::insert(...);
DB::insert(...);


DB::commit();
// all good
} catch (\Exception $e) {
DB::rollback();
// something went wrong
}