サポート > リポジトリ > 業務ロジック > モデルをまたがる計算(トランザクション)

ja | en

モデルをまたがる計算は「トラザクション」となります。ここではトランザクションスクリプトの作成方法を説明します。

出庫モデル syukko の登録処理時に、同時に(関連する)在庫モデル zaiko の値を変更する例を説明します。

図1 在庫管理システムのイメージ

「商品」と「商品在庫」は 1:1 の関係があります。このため、「商品在庫」の主キーは、「商品」を参照するようにしています。

ここではトランザクション系である「出庫伝票」に注目します。このモデルの新規登録処理で、商品在庫を同時に変動させる必要があります。また、商品在庫を超える出庫要求については、エラーを返すようにします。

商品在庫マスタモデルに、図2に示す初期データを設定しました。それぞれ在庫数を100としています。

図2 商品在庫マスタモデルの初期値

出庫伝票を作成します。指定商品を一つ、出庫します。(図3)

図3 出庫伝票の新規作成

出庫伝票が作成されました。このタイミングでトランザクション処理が正常に終了しています。

図4 出庫伝票作成時にトランザクション処理も動作している

商品在庫マスタを確認します。在庫が減じられていることがわかります。

図5 在庫が減じられている

エラー時の扱い

在庫数を超える数を出庫しようとするとエラーメッセージを返すようにしました。(図6)
この場合はデータベースの値は書き変わりません。

図6 トランザクション失敗

図1に示した4つのモデルを定義します。

図7 定義した4つのモデル

倉庫マスタ

倉庫IDと倉庫名、倉庫の管理者を定義しました。

図8 倉庫マスタ

商品マスタ

商品ID、商品名、単価を保持します。また、一つの倉庫に紐付けられます。

図9 商品マスタ

商品在庫マスタ

主キーである「商品」は、商品マスタと 1:1 の関連を持ちます。

主キー「商品」項目は、順序を使わない設定としてください。

図10 商品在庫マスタ

出庫伝票

どの商品をいくつ出庫したかを記録します。

図11 出庫伝票

ここで商品の出庫数に合わせて、商品在庫マスタの在庫数量を減らすために、モデル参照項目「商品」にトランザクションの設定を行います。(図12)
ここでは、新規登録時に「在庫」モデルと連動する指定を行います。

図12 トランザクション設定
モデル名を明記しているのは、今回のケースにおいては(参照先のモデルが)「商品」ではなく「商品在庫」となっているためです。「商品」と「商品在庫」は 1:1 の関係にあり、「商品在庫」の主キーは、「商品」の主キーと同じという関係としています。
参照先モデルがそのままトランザクション処理の対象モデルに等しい場合は、モデル名を空白とすることもできます。本欄が空白の場合は、参照モデル名が利用されます。

新しくトランザクションを設定したとき(新規登録・更新・削除・コピー登録のチェックを行ったとき)は、ビルド処理を行ってください。
一度設定したあとは、ビルド処理は不要です。トランザクションスクリプトの変更は即座に反映されます。

図13 ビルド処理

実際のトランザクション処理コード(トランザクションスクリプト)は、図12における「トランザクション制御時のスクリプト」欄に記述します。

var suryou = zaiko.suryou;
var syukko_num = syukko.syukkoNum;
if (suryou - syukko_num < 0) {
  return "在庫 "+suryou+" に対して "+syukko_num+" を出庫しようとしました。";
}
zaiko.suryou = suryou - syukko_num;
return null;
  • スクリプトでは、return 命令で一つの戻り値を返すようにします。戻り値が null の場合は正常と扱われます。エラーの場合はエラーメッセージ(文字列)を返すようにします。
  • 「新規登録」「更新」「削除」のいずれかを指定します。それぞれのタイミングでトランザクションスクリプトを記述できます。
  • 登録処理とコピー登録処理の区別はありません。SCREENTYPE 定数を用いて判別することができます。これは画面種別を返すSCREENTYPE関数の値を保持しています。
    新規登録時とコピー登録時は同じスクリプトファイルが呼ばれますが、コピー登録時は処理しないような制御を行う例を示します。
    if (SCREENTYPE == "copy") {
        /* コピー登録時は処理を行わない */
        return null;
    }
    /* 登録時にのみ実行される */
    ...
    }
    

実行例

繰り返しコンテナ内の項目にトランザクションを指定することができます。
図14は、出庫伝票の明細で、複数の商品を同時に指定する例です。

図14 出庫伝票に明細を(繰り返しコンテナとして)用意する

同時に複数のデータが書き換えられていることがわかります。(図15)

図15 トランザクションが成功している

設定方法

図11の出庫伝票の定義を変更し、明細を用意しました。(図16)

図16 明細を用意した出庫伝票の定義

トランザクションスクリプトの変更

ファイル名やファイルの保存位置は変わりません。
スクリプト内では、繰り返しコンテナ "details" を利用できます。このとき、複数の繰り返しコンテナのデータ毎に、このスクリプトが実行されます。(図16では3つの明細データがあったため、各データ単位でこのスクリプトが合計3回、実行されます。)

/* トランザクションで使うオブジェクト sykko, zaiko は利用可能になっている。
   これは定義ファイル「トランザクション指定」に含めたモデルである。
   繰り返しコンテナも利用できる。details という名前のオブジェクトが用意されている。*/
var suryou = zaiko.suryou;

/* detailsは明細データ毎に呼び出された値がセットされる */
var syukko_num = details.syukkoNum;
if (suryou - syukko_num < 0) {
    return "在庫 "+suryou+" に対して "+syukko_num+" を出庫しようとしました。";
}
zaiko.suryou = suryou - syukko_num;
return null;

Wagbyの外部キー関係では、一つの親データが複数の子データを管理できます。 次の例では親モデル名 parent と、子モデル名 child を用いて説明します。

子モデル child は、親モデルを指し示す外部キー項目 pkey を持つとします。このとき、この pkey 項目に対してトランザクションスクリプトを記載できます。

図17 親子モデル関係でのトランザクションスクリプト設定例

上図の例は、子モデル新規登録のタイミングで、子モデルの値を親モデルの項目へ転記するものです。

parent.pname = child.cname;

Wagby の標準では、モデルの更新制御は悲観ロックを用います。これを楽観ロック方式に切り替えることもできます。トランザクション実行時のロックは、指定した方式に準拠して制御されます。

悲観ロックでは、対象となるデータが更新中(更新画面が開いた状態)の場合、登録・更新処理を行おうとすると画面には "失敗した" というエラーメッセージが表示されます。

楽観ロックでは、対象となるデータが別に更新されていた場合、同様にエラーとなります。

いずれの場合も、そのトランザクションは失敗します。これは正しい動作です。

サーバサイドJavaScriptから(Wagbyが自動生成した)Service/Daoクラスを利用できます。またSQLを利用することもできます。

こちらは別ページで説明しています。詳細は「Service/Daoクラス、SQLを利用する」をお読みください。

  • トランザクションを指定できるのは、モデル参照項目または外部キー項目に限定されます。数値・文字列・日付型項目に指定しても無視されます。(動作しません。)
ja | en