[Yii2笔记]013 AR乐观锁(Optimistic Locks) [ 技术分享 ]
说明
学习Yii Framework 2(易2框架)的过程是漫长的,也是充满乐趣的,以下是我学习Yii2框架时对官网英文资料(请参见原文网址)的翻译和代码实现,提供了较完整的代码,供你参考。不妥之处,请多多指正!
原文网址:
http://www.yiiframework.com/doc-2.0/guide-db-active-record.html#optimistic-locks
9、Optimistic Locks(乐观锁)
本文主题:AR乐观锁(Optimistic Locks)
9、乐观锁(Optimistic Locks)
当一条记录的数据被多个用户同时更新时,乐观锁是阻止这种冲突发生的一种方法。例如,用户A和B都在同时编辑同一篇wiki文章,在用户A保存他的内容时,用户B也在同时点击了"Save"按钮尝试保存他的内容。因为用户B实际上是在过期版本文章上进行操作,应该有一个好的方法阻止他存储文章,并给他一些提示信息。
乐观锁可以解决上面的问题,它使用一列为每一行数据记录下版本号,当一行数据使用过期版本号存储时,此行数据将不被存储,并抛出yii\db\StaleObjectException异常。只有当你使用yii\db\ActiveRecord::update()或yii\db\ActiveRecord::delete()更新或删除一条已存在的数据时,乐观锁才会生效。
使用乐观锁的步骤: 1)在数据表中添加一个字段与Active Record类相关联,此字段用于存储每行记录的版本号。此字段最好是整型(在MySQL中它将是BIGINT DEFAULT 0)。 2)重写yii\db\ActiveRecord::optimisticLock()方法返回此字段的名称。 3)在用户输入的Web表单中,添加一个隐藏字段去保存当前记录的版本信息。请确保版本信息有输入验证规则并验证成功。 4)在控制器使用Active Record更新记录数据的动作中,尝试和捕获yii\db\StaleObjectException异常,完成必要的业务逻辑(比如合并变化,提示过期信息)去解决这个冲突。
// ------ view code -------
use yii\helpers\Html;
// ...other input fields
echo Html::activeHiddenInput($model, 'version');
// ------ controller code -------
use yii\db\StaleObjectException;
public function actionUpdate($id)
{
$model = $this->findModel($id);
try {
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('update', [
'model' => $model,
]);
}
} catch (StaleObjectException $e) {
// logic to resolve the conflict
}
}
MongoDB,实现乐观锁的实例:
//在视图中添加一个隐藏表单项
文件位置:
D:\phpwork\basic\views\country\_form.php
源代码:
<?= $form->field($model, 'rec_version')->hiddenInput()->label(false) ?>
文件位置:
D:\phpwork\basic\models\Country.php
源代码:
<?
//在模型中指定锁字段名称
public function optimisticLock() {
return 'rec_version';
}
public function rules() {
return [
//在model中要添加以下验证器:
['rec_version','filter','filter'=>'intval'],
/*
此验证器有两个作用:
1)新建记录时,给rec_version字段赋默认值0
2)将表单中的rec_version转为整型,否则会在锁检测时报错:
Stale Object Exception – yii\db\StaleObjectException
The object being updated is outdated.
*/
......
];
}
public function existRecVersion($attribute) {
if(!$this->isNewRecord){
$haveRec = static::findOne(['_id' =>$this->_id]);
$optimisticLock=$this->optimisticLock();
if($haveRec&&($haveRec[$optimisticLock]!=$this->$attribute)){
$this->addError($attribute,"本条记录已被其他人修改过,请复制出本页面中您已修改过的重要信息后,再刷新页面重新编辑!");
}
}
}
(全文完)
共 0 条回复
没有找到数据。
阿江
注册时间:2015-10-18
最后登录:2024-03-03
在线时长:186小时21分
最后登录:2024-03-03
在线时长:186小时21分
- 粉丝94
- 金钱16816
- 威望160
- 积分20276