ページ・アイテムのソースのセッション・ステートの保持の設定で、リクエストごと(メモリーのみ)とセッションごと(ディスク)のどちらかを選んだ時の違いを、クラシック・レポートとポップアップLOVを使って説明してみます。
準備
セッション・ステートの保持の設定による動作の違いを確認するために、APEXアプリケーションを作成します。
サンプル・データセットのEMP/DEPTに含まれる表EMPを検証に使用します。
SQLワークショップのユーティリティのサンプル・データセットを開き、EMP/DEPTのインストールを実行します。言語は日本語と英語のどちらを選んでも作業は可能です。また、アプリケーションの作成は行いません。
アプリケーション作成ウィザードを実行します。
アプリケーションの名前をセッション・ステートの保持とし、ページの作成をクリックします。
作成するのはクラシック・レポートですが、とりあえず対話モード・レポートを選択します。
ページ名はEMPとします。表またはビュー、クラシック・レポートを選択します。表またはビューとしてEMPを選択します。使用するのはクラシック・レポートのみなので、フォームを含めるのチェックは入れません。
ページの追加をクリックします。
アプリケーションの作成を実行します。
アプリケーションが作成されます。
ページ・デザイナにてクラシック・レポートのページ(ページ番号2)を開きます。
クラシック・レポートのリージョンEmployeesに、ページ・アイテムP2_HIREDATEを作成します。識別のタイプとして日付ピッカーを選択し、ラベルは採用日とします。
最初はソースのセッション・ステートの保持はリクエストごと(メモリーのみ)とします。
リージョンEmployeesのソースのWHERE句として hiredate > :P2_HIREDATE を記述します。送信するページ・アイテムは指定しません。
リージョンEmployeesに、ポップアップLOVのページ・アイテムを作成します。
識別の名前をP2_ENAME、タイプをポップアップLOVとします。ラベルは従業員とします。LOVのタイプにSQL問合せを選択し、SQL問合せとして、クラシック・レポートのソースと同等のSELECT文を記載します。
select ename d, empno r from emp where hiredate > :P2_HIREDATE
追加値の表示はOFFとします。
ソースのセッション・ステートの保持はリクエストごと(メモリーのみ)を選択します。今回のアプリケーションでは、ページ・アイテムP2_ENAMEの値が参照されることはないため、セッション・ステートの保持はセッションごと(ディスク)でもかまいません。どちらを設定しても良い場合は、サーバーへの負荷の少ないリクエストごと(メモリーのみ)を選びます。
このレポートを呼び出すボタンを、ホーム・ページに作成します。
ページ・デザイナでホーム・ページを開きます。
ページ・アイテムP1_HIREDATEを作成します。識別のタイプは日付ピッカー、ラベルは採用日とします。ソースのセッション・ステートの保持はリクエストごと(メモリーのみ)を選択します。
クラシック・レポートのページに移動するボタンを作成します。
識別のボタン名をB_SUBMIT、ラベルを送信とします。動作のアクションはページの送信とします。
ページが送信された後にクラシック・レポートのページに遷移するために、ブランチを作成します。
左ペインでプロセス・ビューを開きます。
ブランチを作成し、識別の名前をレポートを開くとします。動作のタイプとしてページまたはURL(リダイレクト)を選択します。サーバー側の条件のボタン押下時としてB_SUBMITを選択します。
リンク・ビルダー・ダーゲットの設定です。
ターゲットのタイプはこのアプリケーションのページ、ページは2になります。アイテムの設定の名前にP2_HIREDATEを選び、その値として&P1_HIREDATE.を指定します。
以上で検証に使用するアプリケーションは完成しました。
ここまでのアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/maintain-session-state.zip
このアプリケーションを使って、検証を行います。
クラシック・レポートへの遷移にブランチを使う点について
検証に使用するアプリケーションでは、ブランチを作成してクラシック・レポートのページに遷移しています。このときボタンの動作のアクションにこのアプリケーションのページにリダイレクトを選択して、ページ番号2に遷移させると期待した動作にはなりません。
ボタンの動作のアクションにこのアプリケーションのページにリダイレクトを設定すると、ボタンはapex.navigation.redirectを呼び出します。設定されたページ・アイテムはGETリクエストの引数として、サーバーに送信されます。GETリクエストの宛先となるURLはページの生成時に引数を含めて決定され、ページが表示された後のページ・アイテムの変更がURLに反映されることはありません。
簡略化すると、以下のHTML要素が生成されます。
<button onclick='apex.navigation.redirect("/ords/r/apexdev/maintain-session-state/emp?p2_hiredate=レンダリング時のP1_HIREDATEの値&session=セッションID");'>
AタグのHREFの指定が、HTTPのGETで呼び出される動作と同じです。
動作のアクションがページの送信の場合は、apex.submitを呼び出します。画面上のページ・アイテムの値はPOSTリクエストの内容として、すべてサーバーに送信されます。
<button onclick='apex.submit({request: "B_SUBMIT"; validate:true});'>
formタグの内容が、HTTPのPOSTで送信される動作と同じです。
今回のボタンB_SUBMITの動作のアクションを、このアプリケーションのページにリダイレクトに変更してページ番号2に遷移させてみます。ページ・アイテムP1_HIREDATEはホーム・ページが表示された時点では値が無いため、採用日に何を設定してもクラシック・レポートには従業員が表示されません。
ホーム・ページが表示されたときの状況です。
採用日に値を設定し、送信ボタンを押します。
送信ボタンのURLの引数P2_HIREDATEの値は空白なので、ターゲットのページに存在するクラシック・レポートには何も表示されません。
ボタンの
動作の
アクションとして
ページの送信が選択されていると、このような結果にはなりません。
リクエストごと(メモリーのみ)の場合
ページ・アイテムP2_HIREDATEのソースのセッション・ステートの保持が、リクエストごと(メモリーのみ)のときの動作について確認してみます。
採用日に1960/01/01を入力し、送信をクリックします。
ページ・アイテム
P1_HIREDATEの値
1960/01/01が、P2_HIREDATEに渡されます。
ページ・アイテムP2_HIREDATEには1960/01/01が表示されます。
ポップアップLOVP2_ENAMEのSQL問合せに含まれるP2_HIREDATEはNULLとなり、従業員は表示されません。
クラシック・レポートは
P2_HIREDATEに
1960/01/01が割り当てられ、
すべての従業員が一覧されます。
クラシック・レポートにはP2_HIREDATEに1960/01/01といった値が割り当てられるのに、ポップアップLOVはなぜNULLになるのか、その違いですが、
コンポーネント自体がAjaxコールを発行してデータを取得している場合、バインド変数にページ・アイテムの値を割り当てるには、送信するページ・アイテムにそのページ・アイテムを設定する必要があります。
動的アクションのリフレッシュに対応しているコンポーネントは、概ねコンポーネントの表示(HTMLの生成)とデータの取得は独立しているので、データ・ソースにバインド変数が含まれる場合は送信するページ・アイテムの設定が必要になります。
上記の設定ではクラシック・レポートで従業員の一覧が表示されています。クラシック・レポートの属性のパフォーマンスの遅延ロードをONにすると、レポートの表示(HTMLの生成)とデータの取得が非同期で行われるようになります。
この場合、送信するページ・アイテムを設定していないと、P2_HIREDATEがNULLになり従業員が表示されません。
ソースの送信するページ・アイテムにP2_HIREDATEを設定すると、ソースのSELECT文を実行する際にはページ・アイテムP2_HIREDATEの画面上の値を取得し、サーバーに送信します。そのため、取得される従業員はつねにページ・アイテムP2_HIREDATEが評価された結果になります。
ポップアップLOVではカスケードLOVの設定があり、ここで設定したページ・アイテムは、LOVのSQL問合せが実行されるときにサーバーに送信されます。
ページ・アイテムP2_ENAMEのカスケードLOVの親アイテムとしてP2_HIREDATEを設定することにより、ポップアップLOVでも従業員の一覧が表示されます。
これらの設定を行うことにより、クラシック・レポートおよびポップアップLOVの双方で、データ取得時にページ・アイテムP2_HIREDATEが評価されます。
多くのコンポーネントは送信するページ・アイテムの設定を含んでいます。送信するページ・アイテムによる設定では、その時点で画面に表示されている値がサーバーに渡されます。
ページ・アイテムP2_HIREDATEが変更されたときにクラシック・レポートがリフレッシュされるよう、動的アクションを作成します。
ページ・アイテムP2_HIREDATEに動的アクションを作成します。名前をonChange P2_HIREDATEとします。タイミングはデフォルトがそのまま使えます。TRUEアクションにリフレッシュ、影響を受ける要素の選択タイプをリージョン、リージョンとしてEmployeesを選択します。
採用日の値が変更されると、クラシック・レポートのリフレッシュが呼び出されます。データ・ソースとなるSELECT文が実行されるときはつねに送信するページ・アイテムとして指定されているページ・アイテムの値もサーバーに送信されるため、変更された採用日がP2_HIREDATEに割り当てられた結果が、従業員の一覧として表示されます。
ポップアップLOVはカスケードLOVの親アイテムとしてP2_HIREDATEが設定されているため、クラシック・レポートと同様に変更された採用日でLOVの一覧に置き換えられます。
セッションごと(ディスク)の場合
ページ・アイテムP2_HIREDATEのソースのセッション・ステートの保持をセッションごと(ディスク)に変更して、動作を確認します。
今までの設定を残したままだと、ほとんど動作に違いはありません。送信するページ・アイテムが設定されていると、データ・ソースを評価する際にセッション・ステートの保持がどちらであっても、画面上の値をサーバーに送信するためです。
そのため、クラシック・レポートから送信するページ・アイテムの設定を外します。遅延ロードはONのまま変更しません。
また、カスケードLOVからは親アイテムの設定を外します。
採用日に1960/01/01を入力し、送信します。
セッション・ステートの保持が
リクエストごと(メモリーのみ)のときとは異なり、クラシック・レポート、ポップアップLOVともに、ページ・アイテム
P2_HIREDATEが
1960/01/01を割り当てた検索結果が、従業員として一覧されます。
セッション・ステートの保持が
セッションごと(ディスク)となっているため、ページ・アイテム
P2_HIREDATEに
1960/01/01が設定された時点で、セッション・ステートとしてデータベースに保持されています。データ・ソースにバインド変数としてP2_HIREDATEが使われている場合、セッション・ステートに保持されているP2_HIREDATEの値が割り当てられます。
セッション・ステートに保持されているアイテムの値は、
開発者ツール・バーの
セッションの
セッション・ステートの表示から参照することができます。この画面から参照できる値が、バインド変数P2_HIREDATEに割り当てられています。
この状態で、採用日を2022/08/01に変更します。採用日が2022/08/01以降の従業員は存在しません。動的アクションは有効なので、リフレッシュされたクラシック・レポートには従業員は表示されないことが期待されます。しかし、実際はそうならず、従業員の一覧は変わりません。
採用日の変更は画面上だけで、サーバー側に送信されていないためです。
変更されたページ・アイテムの値をサーバーに送信するため、リフレッシュの直前にTRUEアクションを作成します。
識別のアクションとしてサーバー側のコードを実行を選択し、設定のPL/SQLコードとしてnull;を記述します。送信するアイテムとしてP2_HIREDATEを指定します。コードには何も書いていないので、単にP2_HIREDATEの値をサーバーに送信するアクションです。
ページ・アイテムの値が送信されると、セッション・ステートにその値が保存されます。クラシック・レポートやポップアップLOVで、リフレッシュが行われる場合は更新されたセッション・ステートがバインド変数に割り当てられます。
コンポーネントが送信するページ・アイテムの設定を持っているのであれば、わざわざ動的アクションを作成する必要は無いでしょう。
ホーム・ページより採用日に1982/01/23を指定して、クラシック・レポートのページを開きます。
クラシック・レポートでは2名の従業員が選択されています。
ポップアップLOVもSELECT文は同等なので、従業員は2名になります。
採用日を1960/01/01に変更します。動的アクションにより、ページ・アイテムP2_HIREDATEの値1960/01/01がサーバーに送信され、クラシック・レポートがリフレッシュされます。
結果としてクラシック・レポートにはすべての従業員が一覧されます。
ポップアップLOVには変更がなく、従業員は2名です。ポップアップLOVはリフレッシュされていないためです。ポップアップLOVをリフレッシュするためには、カスケードLOVの親アイテムの設定が必要です。
まとめ
- 画面上の値をSQLのバインド変数に割り当てるには、送信するページ・アイテムの設定を使用する。もしくは、それと同等の設定を使用する。(ポップアップLOVの場合はカスケードLOV)。
- 送信するページ・アイテムにてバインド変数にページ・アイテムの値を割り当てている場合、セッション・ステートに値を保持する必要性はほぼない。
- 送信するページ・アイテムの設定を持たないがリフレッシュが可能なコンポーネントであれば、セッション・ステートの保持をセッションごと(ディスク)にし、動的アクションでページ・アイテムの値をサーバーに送信することで対応できる。
- 送信するページ・アイテムの設定がなく、リフレッシュにも対応していないコンポーネントを更新するには、ページの送信を実施する必要がある。
以上です。
Oracle APEXのアプリケーション作成の参考になれば幸いです。
完