国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 語言 > PHP > 正文

Yii2中事務的使用實例代碼詳解

2024-05-04 23:49:36
字體:
來源:轉載
供稿:網友

前言

一般我們做業務邏輯,都不會僅僅關聯一個數據表,所以,會面臨事務問題。

數據庫事務(Database Transaction) ,是指作為單個邏輯工作單元執行的一系列操作,要么完全地執行,要么完全地不執行。 事務處理可以確保除非事務性單元內的所有操作都成功完成,否則不會永久更新面向數據的資源。通過將一組相關操作組合為一個要么全部成功要么全部失敗的單元,可以簡化錯誤恢復并使應用程序更加可靠。一個邏輯工作單元要成為事務,必須滿足所謂的ACID(原子性、一致性、隔離性和持久性)屬性。事務是數據庫運行中的一個邏輯工作單位,由DBMS中的事務管理子系統負責事務的處理。

準備

數據庫引擎為innodb

本文使用的yii版本為2.0.5,只要是2.0以上就沒有問題

運行環境為PHP7.0.0,Mysql5.6

Yii中的事務

處理異常

/*** 測試事務*/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

注意,因為最后的數據沒有插入成功,觸發了事務的回滾,所以數據表沒有新增數據產生。

觸發事務回滾的原因是代碼出現了異常(Exception)。

處理數據失敗

一般來講,我們的運行中的代碼是不會出現這種明顯的異常,這種異常會在開發測試過程中消滅掉。

而真正造成數據需要回滾的是我們的某個業務出現問題,導致沒有寫入部分的數據。

/*** 測試事務*/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

分散的數據處理

由于實際項目的復雜程度,導致我們的數據庫操作分散在不同的Model中。

所以,實際項目的代碼不會是上面的樣子。

模擬需求

接收參數:

名字

性別

簽名

業務處理流程:

接收參數

由發號器得到用戶的uid,發號器對應數據表增加一位數字

把名字、性別、簽名和上一步的uid寫入用戶信息表

初始化用戶余額表

回滾觸發時機:

初始化余額表沒有傳入uid導出沒有寫入數據

實際代碼

//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}

如果把初始化用戶余額部分的user_id沒有傳遞成功,返回的結果如下

"沒有初始化用戶余額"

我們可以針對具體情況定位到錯誤所在位置,及時修改。

事務(Transaction)

從上面的實際代碼可以看出,創建了事務,只要在范圍內,就算是引入的別的Model也能把異常NG返回,完成回滾操作。

一般情況下,整個Yii應用使用了同一個數據庫連接,或者說是使用了單例。

而在yii/db/Connection中,又對事務對象進行了緩存:

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;}}

因此,可以認為整個Yii應用,使用了同一個 Transaction 對象,也就是說, Transaction::_level 在整個應用的生命周期中,是有延續性的。 這是實現事務嵌套的關鍵和前提。

以上所述是小編給大家介紹的Yii2中事務的使用實例代碼詳解,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對VeVb武林網網站的支持!


注:相關教程知識閱讀請移步到PHP教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

主站蜘蛛池模板: 丹东市| 榆树市| 遂昌县| 搜索| 桐城市| 秦皇岛市| 勐海县| 温宿县| 塔河县| 濉溪县| 遂平县| 来安县| 马龙县| 新郑市| 铅山县| 南郑县| 石城县| 永定县| 台中市| 华蓥市| 泸溪县| 确山县| 赤城县| 太原市| 临夏市| 松潘县| 枣庄市| 阿勒泰市| 西乌珠穆沁旗| 高青县| 和硕县| 诏安县| 成安县| 界首市| 望城县| 醴陵市| 原平市| 万全县| 临沧市| 庆阳市| 双桥区|