「楽観的排他制御」という言葉を初めて目にしたのはJavaフレームワークSeasar2のS2Daoにおいてでした。
それまでの開発ではSELECT FOR UPDATEを多用していた気がしますが、以来ほぼすべてのプロジェクトで「楽観的排他制御」のパターンを用いることにしました。統一的でシンプルな仕様だからです。
以下のようなしくみを言います。
- 全てのテーブルには version列(int)またはtimestamp列(timestamp)を用意する。(version列のほうがよいと思います。)
- レコードの更新をするときに version列もwhere句に含め、set句にはversion列をインクリメントする。(timestampの場合はtimestampをセット。)
- update件数が0件だったら例外を投げる。
- 上記動作をDBアクセスライブラリ(ORマッパー)が透過的に取り仕切る。(開発者は意識しない。)
Teeple2 でこれを実現する方法を解説します。
Teeple2のDBアクセスライブラリ Teeple_ActiveRecordでは、insertおよびupdateの実行前に teeple_activerecord_before_insert, teeple_activerecord_before_update という関数の存在を調べ、存在した場合はこれらを実行した後に insert(update)を実行するようになっています。
このhook関数にはエンティティオブジェクト自身が引数として渡ってくるので、ここでversion列をインクリメントしたり条件を追加することによって楽観的排他制御が実現できるわけです。
例えば以下のようなコードをuser.inc.phpに追加します。
function teeple_activerecord_before_update($obj) {
if (property_exists(get_class($obj), 'version') === TRUE) {
// 楽観的排他制御
$obj->setConstraint('version', $obj->version);
$obj->version += 1;
}
return;
}
Teeple2で楽観的排他制御を実現するには はコメントを受け付けていません
sRecordは seasar2の S2JDBC, それをまねて作った拙作teeple2のActiveRecordと似たような使い方でSalesforceのデータを取り扱うことができるPHP5ライブラリです。google codeにオープンソースとして公開していますので是非ご利用ください。
http://code.google.com/p/srecord4p/
SalesforceのAPIでは複数のレコードをまとめて処理することが可能です。これにより通信オーバヘッドを軽減することができます。
Srecord_ActiveRecord#create()が単一レコードの作成だったのに対して、Srecord_Schema::createAll()を使うことで複数レコードを一度に作成できます。
Srecord_Schema::createAll()は Srecordオブジェクトの配列を引数に取り、それらのデータにしたがって全てのレコードをSalesforceに登録します。各レコードの結果は、各オブジェクトのgetState()メソッドで確認することができます。
$a1 = new Sobject_Account();
$a1->Name = 'Scott';
$a2 = new Sobject_Account();
$a2->Name = 'Tigger';
Srecord_Schema::createAll(array($a1,$a2));
if ($a1->getState() === Srecord_ActiveRecord::STATE_SUCCESS) {
// success
} else {
// false
print_r($a1->getErrors());
}
updateAll, upsertAll, deleteAll, undeleteAll も同様です。
$records = Srecord_Account::neu()->eq('Type', 'Prospect')->select();
foreach ($records as $record) {
$record->Type = 'Other';
}
$successAll = Srecord_Schema::updateAll($records);
if (! $successAll) {
// handle error
}
$records = array();
for ($i=0; $i<count($_POST['extid']); $i++) {
$extid = $_POST['extid'][$i];
$name = $_POST['name'][$i];
$account = new Sobject_Account();
$account->extid__c = $extid;
$account->Name = $name;
$records[] = $account;
}
$successAll = Srecord_Schema::upsertAll('extid__c', $records);
if (! $successAll) {
// handle error
}
$records = Srecord_Account::neu()->eq('Type', 'Prospect')->select();
$successAll = Srecord_Schema::deleteAll($records);
if (! $successAll) {
// handle error
}
$records = Srecord_Account::neu()->eq('Type', 'Prospect')->select();
$successAll = Srecord_Schema::undeleteAll($records);
if (! $successAll) {
// handle error
}
SalesforceのデータにアクセスするためのPHP5ライブラリ「sRecord」の使い方(8) はコメントを受け付けていません
sRecordは seasar2の S2JDBC, それをまねて作った拙作teeple2のActiveRecordと似たような使い方でSalesforceのデータを取り扱うことができるPHP5ライブラリです。google codeにオープンソースとして公開していますので是非ご利用ください。
http://code.google.com/p/srecord4p/
今日はdelete, undelete について説明します。非常に簡単です。
delete()の引数にIdを指定する方法と、エンティティのプロパティにIdをセットする方法があります。
$result = Sobject_Account::neu()->delete('xxxxxxxxxxxxxxxx');
または
$account = new Sobject_Account();
$account->Id = 'xxxxxxxxxxxxxxxx';
$result = $account->delete();
undeleteは削除を取り消す機能です。こちらも使い方はdeleteと同じです。
$result = Sobject_Account::neu()->undelete('xxxxxxxxxxxxxxxx');
または
$account = new Sobject_Account();
$account->Id = 'xxxxxxxxxxxxxxxx';
$result = $account->undelete();
SalesforceのデータにアクセスするためのPHP5ライブラリ「sRecord」の使い方(7) はコメントを受け付けていません
sRecordは seasar2の S2JDBC, それをまねて作った拙作teeple2のActiveRecordと似たような使い方でSalesforceのデータを取り扱うことができるPHP5ライブラリです。google codeにオープンソースとして公開していますので是非ご利用ください。
http://code.google.com/p/srecord4p/
今日はupsertについて説明します。
指定したカラムの値が同じレコードが存在したらUPDATE,存在しなければINSERTを行なう機能です。
upsert()メソッドの第一引数に`外部ID`となるカラム名をセットします。指定したカラム名でUPDATE or INSERTを判断します。
下記の例では JyugyoinBango__c の値が 123456 でupsertを行ないます。
$extid = '123456';
$j = new Sobject_Jyugyoin__c();
$j->Name = "Test Member";
$j->JyugyoinBango__c = $extid;
$j->Age__c = 30;
$result = $j->upsert('JyugyoinBango__c');
戻り値はBooleanです。成功した場合はエンティティのIdに値がセットされます。
エラーとなった場合は getErrors()メソッドでerrorオブジェクト(エラーに関する情報)を取得できます。
SalesforceのデータにアクセスするためのPHP5ライブラリ「sRecord」の使い方(6) はコメントを受け付けていません
sRecordは seasar2の S2JDBC, それをまねて作った拙作teeple2のActiveRecordと似たような使い方でSalesforceのデータを取り扱うことができるPHP5ライブラリです。google codeにオープンソースとして公開していますので是非ご利用ください。
http://code.google.com/p/srecord4p/
今日はupdate(データの更新)について説明します。
エンティティにセットしたプロパティのみ更新する update()と、全プロパティ(値がセットされていなければNULLになる)を更新するupdateEntity()があります。
更新したいプロパティに新しい値をセットし update() を実行します。
プロパティにNULLをセットしたいときは fieldnull() を使うか、update()メソッドの第一引数に配列(NULLにしたいプロパティ名)で渡します。
$account = new Sobject_Account();
$account->Id = '0018000000UoDxpAAF';
$account->Name = 'Tigger';
$account->fieldnull('ParentId');
$result = $account->update();
if (! $result) {
print_r($account->getErrors());
}
update()は空のプロパティを更新しないのに対して updateEntity()は全てのプロパティを更新します。(空のプロパティはNULLになります。)
このメソッドは select()で取得したものを更新するのに役立ちます。
$account = Sobject_Account::neu()->find('0018000000UoDxpAAF');
$account->Name = 'Tigger';
$account->ParentId = NULL;
$result = $account->updateEntity();
SalesforceのデータにアクセスするためのPHP5ライブラリ「sRecord」の使い方(5) はコメントを受け付けていません