关于数据库事务提交位置的疑惑
今天和同事在讨论关于事务这块,在事务提交位置发生了分歧,我也尝试了一下,不管是同事主张的写法,还是我的写法,都能达到效果,但是谁也说服不了谁,因此想请教一下,哪种方式更合理?实例代码:
// 我主张的写法。
public function test() {
DB::beginTransaction();
try {
$user = UserInfo::query()->create([
"name" => "李大",
"age" => 18
]);
$book = Book::query()->create([
"name" => "测试书籍1",
"user_id" => $user->id
]);
DB::commit();
if ($book) {
return("提交成功");
}
throw new Exception("提交失败");
} catch (Exception $exception) {
DB::rollback();
throw new Exception($exception->getMessage());
}
}
// 同事主张的写法:
public function test() {
DB::beginTransaction();
try {
$user = UserInfo::query()->create([
"name" => "李大asdadasdasd",
"age" => 18
]);
$book = Book::query()->create([
"name" => "测试书籍1",
"user_id" => $user->id
]);
if ($book) {
DB::commit();
return("提交成功");
}
throw new Exception("提交失败");
} catch (Exception $exception) {
DB::rollback();
throw new Exception($exception->getMessage());
}
}
我主张的写法理由是:返回的结果是在事务都提交成功以后去获取,并不需要在最后一个新增成功以后再去提交。事务本身就是都为真true
才会提交,有一个为false
就回滚并且抛出异常。
同事的理由是,使用server
,Repository
模式的时候,控制器调用server层的业务代码,会存在很多条件判断和保存不成功的情况,因此需要判断最后一个为true的时候才提交。
针对这一点,我提出的反驳是,如果在控制器层使用的try,catch
,server
层代码中有异常就可以抛出,这样的话就能及时捕获异常。
但是谁也说服不了谁,请问谁的主张更为合理一点,或者说针对的是不同的场景和业务?
事物提交了以后还可以回滚吗?
赞成你同事的写法
if ($book) {}
这里是判断数据是否有问题如果不判断数据是否存在问题,事务的作用会打折的。
你们的争论焦点应该是这个,如果数据存在问题, 还需要写入数据库吗?
可以试试事务的闭包写法,全局捕捉异常。
只有我看不明白为什么要加判断吗?
还有这个异常什么情况才会抛出呢?
如果
$book
保存成功会走到return
,如果不成功框架应该会抛出异常吧所以直接这样是不是就行了。
首先你这个业务创建为什么会失败?如果失败了是属于什么异常?外层的异常捕获是捕获你运行发生的异常但是你主动抛出的这个异常明显就很奇怪无论它有没有创建成功你都不应该抛出异常而是应该提示,再一个你这个关联是必须有的吗?第一个创建失败那么第二个其实成不成功都无所谓这种怎么能成为一个事务,如果第一个用户创建失败那么这本是肯定创建失败所有看你业务怎么需要怎么实现。。
我会这样写:
明确告诉你把,insert语句在没有产生异常的情况下,是一定有影响记录数返回的,你那个 if 就是多余的。然后说 update语句,大部分业务场景,也是不需要判断返回值的,只关注语句有没有产生异常就好了,少部分需要关注返回值确定有影响记录的行数,这时候才加 if 判断
不如先讨论一下什么情况下既创建失败,又不触发 Exception。。。
为啥你们都把
DB::beginTransaction();
写在try catch
之外呢 我都是写在里面的