Eloquent ORM 非常好,但我想知道是否有一种简单的方法可以使用 innoDB 以与 PDO 相同的方式设置 MySQL 事务,或者我是否必须扩展 ORM 才能实现这一点?
7 回答
你可以这样做:
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();
}
如果你想使用 Eloquent,你也可以使用这个
这只是我项目中的示例代码
/*
* 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();
});
如果你想避免闭包,并且乐于使用门面,下面的代码可以保持整洁:
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();
}
由于某种原因,在任何地方都很难找到此信息,因此我决定将其发布在这里,因为我的问题虽然与 Eloquent 交易有关,但恰恰改变了这一点。
在阅读了这个stackoverflow 答案后,我意识到我的数据库表使用的是 MyISAM 而不是 InnoDB。
对于在 Laravel(或其他任何地方)上工作的事务,需要将您的表设置为使用 InnoDB
为什么?
引用 MySQL Transactions 和 Atomic Operations文档(此处):
MySQL 服务器(版本 3.23-max 和所有版本 4.0 及以上)支持使用 InnoDB 和 BDB 事务存储引擎的事务。InnoDB 提供完全的 ACID 合规性。请参阅第 14 章,存储引擎。有关 InnoDB 在处理事务错误方面与标准 SQL 的差异的信息,请参阅第 14.2.11 节,“InnoDB 错误处理”。
MySQL 服务器中的其他非事务性存储引擎(例如 MyISAM)遵循不同的数据完整性范式,称为“原子操作”。在事务方面,MyISAM 表实际上总是在 autocommit = 1 模式下运行。原子操作通常提供可比的完整性和更高的性能。
因为 MySQL Server 支持这两种范式,您可以决定是通过原子操作的速度还是使用事务特性来最好地服务于您的应用程序。可以在每个表的基础上做出此选择。
如果发生任何异常,事务将自动回滚。
Laravel 基本交易格式
try{
DB::beginTransaction();
/*
* SQL operation one
* SQL operation two
..................
..................
* SQL operation n */
DB::commit();
/* Transaction successful. */
}catch(\Exception $e){
DB::rollback();
/* Transaction failed. */
}