1

我正在构建一个 Web 应用程序,并且我知道可能存在问题。

我有一个控制器,其中有一个store方法。此方法在数据库中创建多个插入。

public function store(LocationPostRequest $request)
{
  $location = Location::create([...]);
  $order = new Order([...]);
  $location->order()->save($order);
  $contact = Contact::findOrFail(id);
  $order->contacts()->save($contacts);
  Transaction::create([])
}

如您所见,我有很多插入。

如果发生错误(或者如果用户在某个时候失去了连接),它将破坏我的数据库的完整性,因为我的方法将添加第一个元素而不是其他元素。

我这样想是对的吗?如何避免这种情况?

4

3 回答 3

3

您可以使用 laravel 数据库事务。

如果任何数据库查询失败,它将自动回滚先前的查询。
DB::transaction(function () {
    //set of queries
   //example 
   DB::table('users')->update(['votes' => 1]);
   DB::table('posts')->delete();
});
于 2020-07-10T09:42:58.020 回答
1

是的,你完全正确。您关心的是数据库的普遍问题。经典的例子是银行转账,就是你给我汇款。金额需要从你的钱中扣除并添加到我的钱中。如果它在第一次操作时失败,那么运气不好,但至少没有人会赔钱。如果它在中间的某个地方失败,在从你身上减去钱之后,但在它被添加到我之前,那么你将很难说服我你实际上已经发送了金额,而你已经失去了给定的金额。

您的情况类似,可能风险较小,但如果出现故障,确保在操作之前恢复您的数据库状态仍然很重要。这就是产生这样一种想法的原因,即一些操作应该相互形成原子绑定,它们应该一起成功,或者一起失败。这种操作的结合称为事务

您可能使用的 RDBMS 实例支持事务,请参阅https://www.tutorialspoint.com/dbms/dbms_transaction.htm

交易是:

  • 一个原子
  • 一致
  • 耐用_
  • 解脱了

这些共同构成了 ACID 原理,您在担心中直观地发现了它。Laravel 有自己的事务支持,你可以通过

DB::transaction($somefunction)

你的工作是将你的函数作为参数传递给DB::transaction并且不用担心,因为在失败的情况下 Laravel 声称会发生回滚。不过,我当然会进行测试,因为正如温斯顿丘吉尔所说:

无论策略多么漂亮,你都应该偶尔看看结果。

于 2020-07-10T09:54:23.897 回答
0

您可以将 try 和 catch 与 DB:transaction() 一起使用。

try {
        //start the transaction
        DB::beginTransaction();

        //You code

        //commit the transaction
        DB::commit();
} catch (\Exception $e) {
        DB::rollBack();
        return response;
}

希望这可以帮助

于 2020-07-10T10:28:14.430 回答