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 |
|
TOTAL_AMOUNT |
NUMBER |
|
ORDERLINES |
配列 |
|
ORDERLINES_QUANTITY ORDERLINES |
NUMBER |
|
ORDERLINES_PRODUCTNAME ORDERLINES |
VARCHAR2 |
|
FULFILLMENTS ORDERLINES |
配列 |
|
FULLFILLMENTS_QUANTITY FULFILLMENTS |
NUMBER |
|
FULLFILLMENTS_WAREHOUSE FULFILLMENTS |
VARCHAR2 |
|
ある注文(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;