Yii2中事务的使用实例代码详解
框架(架构)  /  管理员 发布于 7年前   126
前言 一般我们做业务逻辑,都不会仅仅关联一个数据表,所以,会面临事务问题。 数据库事务(Database Transaction) ,是指作为单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行。 事务处理可以确保除非事务性单元内的所有操作都成功完成,否则不会永久更新面向数据的资源。通过将一组相关操作组合为一个要么全部成功要么全部失败的单元,可以简化错误恢复并使应用程序更加可靠。一个逻辑工作单元要成为事务,必须满足所谓的ACID(原子性、一致性、隔离性和持久性)属性。事务是数据库运行中的一个逻辑工作单位,由DBMS中的事务管理子系统负责事务的处理。 准备 数据库引擎为innodb 本文使用的yii版本为2.0.5,只要是2.0以上就没有问题 运行环境为PHP7.0.0,Mysql5.6 Yii中的事务 处理异常 运行结果 注意,因为最后的数据没有插入成功,触发了事务的回滚,所以数据表没有新增数据产生。 触发事务回滚的原因是代码出现了异常(Exception)。 处理数据失败 一般来讲,我们的运行中的代码是不会出现这种明显的异常,这种异常会在开发测试过程中消灭掉。 而真正造成数据需要回滚的是我们的某个业务出现问题,导致没有写入部分的数据。 运行结果如下,数据库插入了三条数据。 也就是说,如果因为业务逻辑导致某个数据表没有写入数据,也没有出现对应的回滚。 改进方案如下 运行结果如下,数据库没有插入新数据,事务被回滚。 分散的数据处理 由于实际项目的复杂程度,导致我们的数据库操作分散在不同的Model中。 所以,实际项目的代码不会是上面的样子。 模拟需求 接收参数: 名字 性别 签名 业务处理流程: 接收参数 由发号器得到用户的uid,发号器对应数据表增加一位数字 把名字、性别、签名和上一步的uid写入用户信息表 初始化用户余额表 回滚触发时机: 初始化余额表没有传入uid导出没有写入数据 实际代码 正常的结果如下 如果把初始化用户余额部分的user_id没有传递成功,返回的结果如下 我们可以针对具体情况定位到错误所在位置,及时修改。 事务(Transaction) 从上面的实际代码可以看出,创建了事务,只要在范围内,就算是引入的别的Model也能把异常NG返回,完成回滚操作。 一般情况下,整个Yii应用使用了同一个数据库连接,或者说是使用了单例。 而在yii\db\Connection中,又对事务对象进行了缓存: 因此,可以认为整个Yii应用,使用了同一个 Transaction 对象,也就是说, Transaction::_level 在整个应用的生命周期中,是有延续性的。 这是实现事务嵌套的关键和前提。 以上所述是小编给大家介绍的Yii2中事务的使用实例代码详解,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对站的支持!/*** 测试事务*/public function actionTest(){//创建事务$tr = Yii::$app->db->beginTransaction();try {for($i=1;$i<=3;$i++){$test = new Areas();$test->name = 'name'.$i;$test->sort=1;if($test->save()){echo "save $i | ";}}$test = new Areas();$test->name = 'ab'.$i;$test->sorta=1; //写入不存在的字段if(!$test->save()){"save fail"; //如果没有写入就输出}//提交$tr->commit();} catch (Exception $e) {//回滚$tr->rollBack();echo "rollback";}}
save 1 | save 2 | save 3 | rollback
/*** 测试事务*/public function actionTest(){//创建事务$tr = Yii::$app->db->beginTransaction();try {for($i=1;$i<=3;$i++){$test = new Areas();$test->name = 'name'.$i;$test->sort=1;if($test->save()){echo "save $i | ";}}$test = new Areas();$test->name = null; //数据库设计name不能为空,人为造成写入失败。$test->sort=1; //写入不存在的字段if(!$test->save()){echo "save fail"; //如果没有写入就输出}//提交$tr->commit();} catch (Exception $e) {//回滚$tr->rollBack();echo "rollback";}}
save 1 | save 2 | save 3 | save fail
/*** 测试事务*/public function actionTest(){//创建事务$tr = Yii::$app->db->beginTransaction();try {for($i=1;$i<=3;$i++){$test = new Areas();$test->name = 'name'.$i;$test->sort=1;if($test->save()){echo "save $i | ";}}$test = new Areas();$test->name = null; //数据库设计name不能为空,人为造成写入失败。$test->sort=1; //写入不存在的字段if(!$test->save()){throw new \yii\db\Exception(); //手动抛出异常,再由下面捕获。}//提交$tr->commit();} catch (Exception $e) {//回滚$tr->rollBack();echo "rollback";}}
save 1 | save 2 | save 3 | rollback
//Controller/*** 测试事务-注册用户*/public function actionReg(){//获取请求$request = Yii::$app->request;//设定返回格式$response = Yii::$app->response;$response->format = \yii\web\Response::FORMAT_JSON; //返回json//测试代码,去掉验证身份步骤$name = $request->get("name");$gender = $request->get("gender");$sign = $request->get("sign");//测试代码,省略参数校验步骤$tr = Yii::$app->db->beginTransaction();try {//得到uid$uid = App::getSeNo();UserProfile::add($uid, $name, $gender, 1, $sign);$user_balance = UserBalance::initUserBalance($uid);$tr->commit(); //提交数据} catch (Exception $e) {//回滚$tr->rollBack();return $e->getMessage(); //返回自定义异常信息}return $user_balance;}//UserProfile/*** 添加用户信息* @param $user_id* @param $nikename* @param $gender* @param $user_type* @param string $intro* @return UserProfile* @throws \Exception*/public static function add($user_id, $nikename, $gender,$user_type,$intro="") {$model = new UserProfile();$model->gender = $gender;$model->nikename = $nikename;$model->user_id = $user_id;$model->user_type=$user_type;$model->intro=$intro;$model->update_time = time();$insert =$model->insert();if(!$insert){throw new Exception("没有写入用户资料");}return $model;}//UserBalance/*** 初始化用户的可提现余额* @param $user_id*/public static function initUserBalance($user_id){$info=self::find()->where(['user_id'=>$user_id])->one();if(!$info ){$model=new UserBalance();$model->user_id = $user_id;$model->price= "0";$model->update_time=time();$insert = $model->insert();if(!$insert){throw new Exception("没有初始化用户余额");}$info=$model;}return $info->attributes;}
{"id":124,"user_id":1473179883,"price":"0","update_time":1473179883}
"没有初始化用户余额"
class Connection extends Component{// 保存当前连接的有效Transaction对象private $_transaction;// 已经缓存有事务对象,且事务对象有效,则返回该事务对象// 否则返回nullpublic function getTransaction(){return $this->_transaction && $this->_transaction->getIsActive() ? $this->_transaction : null;}// 看看启用事务时,是如何使用事务对象的public function beginTransaction($isolationLevel = null){$this->open();// 缓存的事务对象有效,则使用缓存中的事务对象// 否则创建一个新的事务对象if (($transaction = $this->getTransaction()) === null) {$transaction = $this->_transaction = new Transaction(['db' => $this]);}$transaction->begin($isolationLevel);return $transaction;}}
您可能感兴趣的文章:
122 在
学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..123 在
Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..原梓番博客 在
在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..博主 在
佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..1111 在
佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
Copyright·© 2019 侯体宗版权所有·
粤ICP备20027696号