(悲観)ロックテーブル
Wagbyの「悲観ロック」は内部でロックマネージャをもっています。このロックマネージャはメモリ内にロックを保持します。この情報は外部から知ることはできません。
このロック情報を(リレーショナルデータベースの)テーブルに書き込むオプションを用意しています。これによって、外部プログラムから「どのデータがロックされているか」を知ることができるため、ロックされているデータは更新しないといった制御を行うことができます。
さらに、外部プログラム側からロックをかけることで、Wagby側からも更新ができないように制御することもできます。
定義方法
「環境 > カスタマイズ > 詳細 > ロック情報をデータベースのテーブルに格納する」を有効にします。
ロック情報をデータベースのテーブルに格納する
テーブルの作成
ビルド後に init_db.bat を行うことで外部データベースに jfclockobject テーブルが作成されます。
または手動で jfclockobject テーブルだけを(外部データベースに)作成することもできます。コマンドを実行するカレントディレクトリを wagbyapp\bin とします。
R9.0.3以降
java -jar InitLoader.jar create -t jfclockobject -c ..\webapps\wagby\WEB-INF\export\conf\initdb.xml -systempropfile ..\conf\catalina.properties
R9.0.2まで
java -jar InitLoader.jar create -t jfclockobject -c ..\webapps\wagby\WEB-INF\export\conf\initdb.xml
ロック情報を検索する
システム管理者でログオンし、管理処理タブにある「ロック情報検索」画面を開くと、図5のように現在、ロックされているデータが表示されます。
ロック情報を検索する
jfclockobjectテーブル
設定を有効にすると、利用するリレーショナルデータベース内に jfclockobject テーブルが用意されます。
項目名
主キー
説明
modelname
○
ロック対象のモデル名(英語)
pkey
○
ロック対象データの主キーの値。複合キーの場合は"$SEP$"を区切り文字として値を連結する。
lockForAll
○
数値型。"1" が個別データのロック。"2" がモデル全体のロックを意味する。
userid
ロックを取得した(juserアカウントの)userid値。
username
ロックを取得した(juserアカウントの)username値。
machinename
ロックを取得したホストマシンの値。クラスタリング、オートスケール運用で利用する。外部プログラムからロックを取得する場合、Wagbyアプリケーションが使用していない値を設定する。
sessionid
ロックを取得したユーザのセッションID値。
あるデータの更新画面を開くタイミングで、jfclockobject テーブルを検索し、該当データに関するロックが存在するかどうかを確認します。すでにロックが存在していた場合、更新画面を開くことができません。存在しなかった場合、同テーブルにロック情報を書き込みます。更新処理が終了したタイミングで、ロック情報を削除します。
外部からロックを取得する
外部プログラムから jfclockobject テーブルにロック情報(レコード)を追加することで、Wagbyの画面から編集できないようにすることができます。(*3)
jfclockobject テーブルに用意されたすべての列を埋める 必要があります。いずれか一つでも、未設定 (null) であった場合、ロックは取得されません。
項目 modelname, pkey, lockForAll は対象データを指し示すために必要です。
項目 userid, username, sessionid は「誰がロックを取得したか」という情報を記録するために必要です。
なお項目 sessionid は Web アプリケーションサーバが発行するセッションIDが格納されます。しかし外部プログラムからこの値を設定する場合、セッションID を生成することは困難です。例えば Web アプリケーションサーバに Tomcat を利用した場合、セッションIDは32文字のランダム文字列です。原則として、ユニークな文字列であれば動作します。
外部プログラムから値を設定する場合は、何らかのルールを決めると良いでしょう。例えばこの値を次のようにします。
$HOSTNAME$APPLICATIONNAME$SEQUENCEVALUE
このようなルールに基づいて擬似的なセッションID文字列をセットすることで、ユニーク性を保ちつつ、誰がロックしたかも視認しやすくなります。
アプリケーション起動時にロック情報を削除する
R9.0.3より、アプリケーション起動時にjfclockobjectテーブルのロック情報を削除するようになりました。削除した件数をINFOレベルでログ出力します。(削除件数が0の場合はログ出力されません。)
この仕様に伴い、項目 machinename にはWagbyアプリケーションが使用していない値を設定するようにしてください。
これは Wagby アプリケーション起動時にそのアプリケーションの machiename に対応する jfclocktable 内のレコードを削除する仕様となっているためです。
ロックキーのカスタマイズ
Wagbyのロックマネージャの仕組みを理解し、ロックキーをカスタマイズすることができます。(悲観ロック利用時。楽観ロックの場合は、本内容は適用されません。)
Wagby の悲観ロックでは、Wagby内部のロックマネージャを用います。ユーザーがデータの更新画面を開いたタイミングで対象データをロックします。
このとき、対象データのモデル名を「ロック名」とし、主キー項目を「ロック項目」として扱います。ロック名とロック項目の値から「ロックキー」を生成し、これをロックマネージャで管理しています。
ロックキーのカスタマイズとは、このロック名やロック項目を任意に設定できるようにすることです。
さらに、ひとつの更新画面で複数のロックキーを扱えるようにします。
この機能を利用すると、トランザクション処理のためのカスタマイズコードを記述するときに対象データのロック管理を柔軟に制御することができるようになります。
定義方法
「モデル項目詳細定義>詳細>データベースの詳細>ロック名」を指定します。
図3 モデル項目詳細定義
標準は未指定(空白)となっています。対象となるモデルのすべての項目で未指定の場合は、モデル名をロック名とし、主キー項目をロックキーとします。これが通常の動作となります。
値を記載すると、この項目がロックキーとして用いられます。また記載した値がロック名となります。
サンプル
次のモデルを例に示します。
モデル a
モデル b
また、モデルaおよびモデルbのデータが次のようになっているとします。
モデルaのデータ:2つのデータ
項目 ida1 項目 ida2
1 1000 1001
2 1001 1002
モデルbのデータ:2つのデータ
項目 idb1 項目 idb2
1 1000 1001
2 1001 1002
例1:モデル a のデータを更新する際に、モデル b のデータもロックする。
1000番のモデル a のデータを編集すると、1000番のモデル b のデータもロックする。
モデル a 項目 ida1 のモデル項目定義シートの「モデルの関連性 - ロック名」に「b」と指定します。これにより、モデル a のデータを編集する場合でも、ロック名はモデル b と同じになるため、モデル b のデータもロックされることとなります。
例2:モデル a のデータを更新する際に、ida2の値でモデル b もロックする。
1000番のモデル a のデータを編集する場合、ida2は1001なので、1001番のモデル b のデータもロックする。
モデル a 項目 ida2 のモデル項目定義シートの「モデルの関連性 - ロック名」に「b」と指定します。
この設定により、モデル a のデータを更新する場合、ロック名 b ロックキー ida2 の値となるロックを行います。
例3:下記のような複合キーのあるモデル c がある場合に、モデル a を更新する際に、ロックキーとして ida1 と ida2 を使い、モデル c をロックする。
モデル c
モデル a 項目 ida1 のモデル項目定義シートの「モデルの関連性 - ロック名」に「c」と指定します。
モデル a 項目 ida2 のモデル項目定義シートの「モデルの関連性 - ロック名」に「c」と指定します。
一つのモデルにて同じロック名が指定されている場合は、複合キーとして 扱います。
ida1:1000,ida2:1001のモデル a のデータを更新する場合、idc1:1000,idc2:1001のモデル c のデータをロックします。
例4:モデル a を更新する際に、モデル b とモデル c のデータをロックする。
モデル a 項目 ida1 のモデル項目定義シートの「モデルの関連性 - ロック名」に「b c」と指定します。
モデル a 項目 ida2 のモデル項目定義シートの「モデルの関連性 - ロック名」に「c」と指定します。
スペース区切りで複数のロック名を指定することができます。
ida1:1000,ida2:1001のモデル a のデータを更新する場合、idb1:1000のモデル bのデータと、idc1:1000,idc2:1001のモデル c のデータをロックします。
繰り返しコンテナ項目の値を使う場合
繰り返しコンテナ内の項目を使ったロック名の指定を行うことができます。繰り返しコンテナの数に合わせて、ロックを行います。
一つの繰り返し項目、繰り返しコンテナ内の項目に指定した場合
この場合は、n 個のロックオブジェクトが作成されます。
例: 下記のようにcont1/c1contentにロック名が指定されたモデルがあるとします。
項目 主キー ロック名
id ○
cont1
cont1/c1id
cont1/c1content test1
この場合、ロック名をtest1、ロックデータキーにcont1/c1contentを用いてロックを作成します。(*4)
具体的に説明します。このモデルに対応する下記のデータがあるとします。
<test1>
<id>1000</id>
<cont1><c1id>1</c1id><c1content>a </c1content></cont1>
<cont1><c1id>2</c1id><c1content>b </c1content></cont1>
</test1>
この場合、次の2つのロックオブジェクトが内部で用意されます。
ロック名:test1 ロックキー:a
ロック名:test1 ロックキー:b
一つの項目と、一つの繰り返しコンテナ内の項目に指定した場合
この場合は、n 個の複合キーとなる ロックオブジェクトが作成されます。
例: 下記のようにidとcont1/c1contentにロック名が指定されたモデルがあるとします。
項目 主キー ロック名
id ○ test1
cont1
cont1/c1id
cont1/c1content test1
この場合、ロック名をtest1、ロックデータキーにidとcont2/c2contentを用いてロックを作成します。(*5)
具体的に説明します。このモデルに対応する下記のデータがあるとします。
<test1>
<id>1000</id>
<cont1><c1id>1</c1id><c1content>a </c1content></cont1>
<cont1><c1id>2</c1id><c1content>b </c1content></cont1>
</test1>
この場合、次の2つのロックオブジェクトが内部で用意されます。
ロック名:test1 ロックキー:1000$a
ロック名:test1 ロックキー:1000$b
複数の繰り返し項目、繰り返しコンテナ内の項目を指定した場合
この場合は、n*m 個の複合キーとなる ロックオブジェクトが作成されます。
例: 下記のようにcont1/c1contentとcont2/c2content項目にロック名が指定されたモデルがあるとします。
項目 主キー ロック名
id ○
cont1
cont1/c1id
cont1/c1content test1
cont2
cont2/c2id
cont2/c2content test1
この場合、ロック名をtest1、ロックデータキーにcont1/c1contentとcont2/c2contentを用いてロックを作成します。(*6)
具体的に説明します。このモデルに対応する下記のデータがあるとします。
<test1>
<id>1000</id>
<cont1><c1id>1</c1id><c1content>a </c1content></cont1>
<cont1><c1id>2</c1id><c1content>b </c1content></cont1>
<cont2><c2id>1</c2id><c2content>c </c2content></cont2>
<cont2><c2id>2</c2id><c2content>d </c2content></cont2>
</test1>
この場合、次の4つのロックオブジェクトが内部で用意されます。
ロック名:test1 ロックキー:a$c
ロック名:test1 ロックキー:a$d
ロック名:test1 ロックキー:b$c
ロック名:test1 ロックキー:b$d
仕様・制約
ここで説明したロックキーのカスタマイズについてのお問い合わせは Premium Support の対象となります。
モデル参照(チェックボックス)にロック名を指定することはできません。
複数のモデルでロック名を共用する場合に、ロックキーとなる項目の型が一致する必要があります。上記、例1の設定では、モデル a 項目 ida1 とモデル b 項目 idb1 の項目の型が一致しています。
複合キーとして扱われた場合は、設定されている順番と項目の型が一致する必要があります。例3の設定では、項目 ida1 と idc1、項目 ida2 と idc2 の項目の型がそれぞれ一致しています。
ロックキーに指定した項目は更新画面、一覧更新画面で読み込み専用項目となります。
ロックは更新時のみ 行われます。新規登録やコピー登録の際には行われません。(*7)