18.4.8.10 ネストしたコレクションがあるビジネス・オブジェクトの読取り

BOSSビジネス・オブジェクトのネストしたコレクションをプログラムで操作するために配列型のRESTデータ・ソース・プロファイル列を定義します。

配列列を定義するときは、「セレクタ」で親配列からの相対パスを使用します。「リモート属性名」フィールドに、ルートからのフルパスを入力します(それがセレクタと異なる場合)。その後、APEX_EXECパッケージを使用して、ネストした配列を操作できます。このためには、open_array()ファンクションとclose_array()ファンクションを使用して、操作する現在の配列のコンテキストを設定します:

たとえば、Order (注文)ビジネス・オブジェクトを操作しており、それにはOrderLineItem (注文明細項目)ビジネス・オブジェクトからなるコレクションが含まれており、その各オブジェクトにOrderLineFulfillment (注文明細フルフィルメント)オブジェクトからなるコレクションが含まれているとします。次の表に、静的IDがorders_with_detailsである注文詳細(Orders with Details) RESTデータ・ソースからのデータ・プロファイル列の例を示します:

列名/親列 Data Type セレクタ/リモート属性名

ORDER_STATUS

VARCHAR2

orderStatus

TOTAL_AMOUNT

NUMBER

totalAmount

ORDERLINES

配列

orderLines.items

ORDERLINES_QUANTITY

ORDERLINES

NUMBER

quantity

orderLines.quantity

ORDERLINES_PRODUCTNAME

ORDERLINES

VARCHAR2

product.productName

orderLines.product.productName

FULFILLMENTS

ORDERLINES

配列

fulfillments.items

orderLines.fulfillments.items

FULLFILLMENTS_QUANTITY

FULFILLMENTS

NUMBER

quantity

orderLines.fulfillments.quantity

FULLFILLMENTS_WAREHOUSE

FULFILLMENTS

VARCHAR2

warehousedProduct.warehouse.name

orderLines.fulfillments.warehousedProduct.warehouse.name

ある注文(get_order()ファンクションにそのIDが渡される)について3レベルのデータ階層を取得するには、次のサンプル・ファンクションのようにコードを記述します。

function get_order_exec(
   p_order_id in number)
   return t_order
is
   l_order t_order;
   l_ctx apex_exec.t_context;
   l_additional varchar2(255);
   l_cur_line t_order_line;
   l_ord_line pls_integer;
   l_ful_line pls_integer;
begin
   -- get_order_columns() returns apex_exec.t_columns for all fields
   l_ctx := apex_exec.open_rest_source_query(
      p_static_id               => 'orders_with_details',
      p_columns                 => get_order_columns,
      p_external_filter_expr    => 'orderId = '||p_order_id);
   if apex_exec.next_row(l_ctx) then
      l_order.order_id := apex_exec.get_number(l_ctx, 'ORDERID');
      l_order.tax_amount := apex_exec.get_number(l_ctx, 'TAXAMOUNT');
      l_order.total_amount := apex_exec.get_number(l_ctx, 'TOTALAMOUNT');
      l_order.order_date := apex_exec.get_date(l_ctx, 'ORDERDATE');
      l_order.order_status := apex_exec.get_varchar2(l_ctx, 'ORDERSTATUS');
      l_order.customer_first_name := apex_exec.get_varchar2(l_ctx, 'CUSTOMER_FIRSTNAME');
      l_order.customer_last_name := apex_exec.get_varchar2(l_ctx, 'CUSTOMER_LASTNAME');
      l_order.customer_phone := apex_exec.get_varchar2(l_ctx, 'CUSTOMER_PHONE');
      l_order.customer_email := apex_exec.get_varchar2(l_ctx, 'CUSTOMER_EMAILADDRESS');
      l_order.customer_loyalty_level := apex_exec.get_varchar2(l_ctx, 'CUSTOMER_LOYALTYLEVEL');
      l_additional := apex_exec.get_varchar2(l_ctx, 'SHIPTO_ADDITIONAL');
      l_order.ship_address := apex_exec.get_varchar2(l_ctx, 'SHIPTO_ADDRESS')
                              || case when l_additional is not null then ', ' end
                              || l_additional;
      l_order.ship_city := apex_exec.get_varchar2(l_ctx, 'SHIPTO_CITY');
      l_order.ship_state := apex_exec.get_varchar2(l_ctx, 'SHIPTO_STATE');
      l_order.ship_zip := apex_exec.get_varchar2(l_ctx, 'SHIPTO_ZIP');
      -- open & loop over Order Lines for current order
      apex_exec.open_array(l_ctx,'ORDERLINES');
      while apex_exec.next_array_row(l_ctx) loop
          l_ord_line := l_order.order_lines.count + 1;
          l_order.order_lines(l_ord_line).quantity
               := apex_exec.get_number(l_ctx, 'ORDERLINES_QUANTITY');
          l_order.order_lines(l_ord_line).list_price
               := apex_exec.get_number(l_ctx, 'ORDERLINES_LISTPRICE');
          l_order.order_lines(l_ord_line).amount
               := apex_exec.get_number(l_ctx, 'ORDERLINES_AMOUNT');
          l_order.order_lines(l_ord_line).product_name
               := apex_exec.get_varchar2(l_ctx, 'ORDERLINES_PRODUCTNAME');
          -- open & loop over Order Line Fulfillments for current order line
          apex_exec.open_array(l_ctx,'FULFILLMENTS');
          while apex_exec.next_array_row(l_ctx) loop
              l_ful_line := l_order.order_lines(l_ord_line).fulfillments.count + 1;
              l_order.order_lines(l_ord_line).fulfillments(l_ful_line).quantity
                  := apex_exec.get_number(l_ctx, 'FULFILLMENTS_QUANTITY');
              l_order.order_lines(l_ord_line).fulfillments(l_ful_line).warehouse_name
                  := apex_exec.get_varchar2(l_ctx, 'FULFILLMENTS_WAREHOUSE');
          end loop;
          apex_exec.close_array(l_ctx);
      end loop;
      apex_exec.close_array(l_ctx);
  end if;
  apex_exec.close(l_ctx);
  return l_order;
end get_order_exec;

前述のコードでは、次に示すget_order_columns()ファンクションが参照されます。それによって、その問合せに関与する列を定義するapex_exec.t_columnレコードのapex_exec.t_columns表が返されます。

function get_order_columns
return apex_exec.t_columns
is
    l_columns apex_exec.t_columns;
begin
    apex_exec.add_column( /* orderId */
        p_columns         => l_columns,
        p_column_name     => 'ORDERID',
        p_data_type       => apex_exec.c_data_type_number);
    apex_exec.add_column( /* orderDate */
        p_columns         => l_columns,
        p_column_name     => 'ORDERDATE',
        p_data_type       => apex_exec.c_data_type_date);
    -- etc. (other top-level columns here)
    apex_exec.add_column( /* orderLines.items */
        p_columns         => l_columns,
        p_column_name     => 'ORDERLINES',
        p_data_type       => apex_exec.c_data_type_array);
    apex_exec.add_column( /* orderLines.product.productName */
        p_columns         => l_columns,
        p_column_name     => 'ORDERLINES_PRODUCTNAME',
        p_data_type       => apex_exec.c_data_type_varchar2,
        p_parent_column_path => '"ORDERLINES"');
    apex_exec.add_column( /* orderLines.quantity */
        p_columns         => l_columns,
        p_column_name     => 'ORDERLINES_QUANTITY',
        p_data_type       => apex_exec.c_data_type_number,
        p_parent_column_path => '"ORDERLINES"');
    apex_exec.add_column( /* orderLines.listPrice */
        p_columns         => l_columns,
        p_column_name     => 'ORDERLINES_LISTPRICE',
        p_data_type       => apex_exec.c_data_type_number,
        p_parent_column_path => '"ORDERLINES"');
    apex_exec.add_column( /* orderLines.amount */
        p_columns         => l_columns,
        p_column_name     => 'ORDERLINES_AMOUNT',
        p_data_type       => apex_exec.c_data_type_number,
        p_parent_column_path => '"ORDERLINES"');
    apex_exec.add_column( /* orderLines.fulfillments.items */
        p_columns         => l_columns,
        p_column_name     => 'FULFILLMENTS',
        p_data_type       => apex_exec.c_data_type_array,
        p_parent_column_path => '"ORDERLINES"');
    apex_exec.add_column( /* orderLines.fulfillments.warehousedProduct.warehouse.name */
        p_columns         => l_columns,
        p_column_name     => 'FULFILLMENTS_WAREHOUSE',
        p_data_type       => apex_exec.c_data_type_varchar2,
        p_parent_column_path => '"ORDERLINES"."FULFILLMENTS"');
    apex_exec.add_column( /* orderLines.fulfillments.quantity */
        p_columns         => l_columns,
        p_column_name     => 'FULFILLMENTS_QUANTITY',
        p_data_type       => apex_exec.c_data_type_number,
        p_parent_column_path => '"ORDERLINES"."FULFILLMENTS"');
    return l_columns;
end get_order_columns;