ヘッダーをスキップ
Oracle OLAP Java API開発者ガイド
11g リリース1(11.1)
E05733-01
  目次へ
目次
索引へ
索引

前へ
前へ
 
次へ
次へ
 

9 問合せ結果の取得

この章では、Oracle OLAP Java APIのCursorを使用して問合せの結果を取得する方法およびその結果にアクセスする方法について説明します。また、結果の表示方法に合せてCursorの動作をカスタマイズする方法についても説明します。Cursorのクラス階層や関連するクラス、およびCursorの位置、フェッチ・サイズおよびエクステントの概念については、第8章「CursorクラスおよびCursorの概念」を参照してください。

この章では、次の項目について説明します。

問合せ結果の取得

問合せは、データ・ストアから取得するデータや、そのデータに対してOracle OLAPを使用して実行する任意の計算を指定するOLAP Java APIのSourceです。Cursorは、Sourceによって指定された結果セットを取得(フェッチ)するオブジェクトです。Source用のCursorを作成するには、次の手順を実行します。

  1. MdmObjectからプライマリSourceを取得します。または、DataProviderまたはSourceを操作して導出Sourceを作成します。Sourceオブジェクトの取得または作成の詳細は、第5章「Sourceオブジェクトの理解」を参照してください。

  2. Sourceが導出Sourceの場合、Sourceを作成したTransactionをコミットします。Transactionをコミットするには、TransactionProvidercommitCurrentTransactionメソッドをコールします。Transactionのコミットの詳細は、第7章「TransactionProviderの使用方法」を参照してください。SourceがプライマリSourceの場合、Transactionをコミットする必要はありません。

  3. DataProvidercreateCursorManagerメソッドをコールし、そのメソッドにSourceを渡すことによって、CursorManagerを作成します。

  4. CursorManagercreateCursorメソッドをコールして、Cursorを作成します。

例9-1では、querySourceという名前の導出Source用のCursorが作成されます。この例では、dpという名前のDataProviderを使用します。例では、cursorMngrという名前のCursorManager、およびqueryCursorという名前のCursorが作成されます。

最後にCursorManagerがクローズされます。Cursorの使用が終了したら、CursorManagerをクローズしてリソースを解放する必要があります。

例9-1 Cursorの作成

CursorManager cursorMngr = dp.createCursorManager(querySource);
Cursor queryCursor = cursorMngr.createCursor();

// Use the Cursor in some way, such as to display its values.

cursorMngr.close();

Cursorからの値の取得

現在の位置の概念は、Cursorインタフェースによってカプセル化されます。このインタフェースには、現在の位置を移動するためのメソッドがあります。ValueCursorおよびCompoundCursorインタフェースは、Cursorインタフェースを拡張します。Oracle OLAP Java APIには、ValueCursorおよびCompoundCursorインタフェースの実装が存在します。CursorManagercreateCursorメソッドをコールすると、Cursorを作成中のSourceに応じて、ValueCursor実装またはCompoundCursor実装が戻されます。

単一の値セットを持つSourceに対して、ValueCursorが戻されます。ValueCursorは、現在の位置に値が含まれており、現在の位置の値を取得するためのメソッドを持ちます。

2つ以上の値セットを持つSource(1つ以上の出力を持つSource)に対しては、CompoundCursorが作成されます。Sourceの各値セットは、CompoundCursorの子ValueCursorによって表されます。CompoundCursorは、その子Cursorオブジェクトを取得するためのメソッドを持ちます。

Cursorの構造はSourceの構造によって決まります。Sourceはネストされた出力を持つ場合があります。これは、Sourceの1つ以上の出力自体が、出力を持つSourceである場合に発生します。Sourceがネストされた出力を持つ場合、Source用のCompoundCursorには、ネストされた出力用の子CompoundCursorが存在します。

CompoundCursorによって、その子Cursorオブジェクトの位置が調整されます。CompoundCursorの現在の位置によって、その子Cursorオブジェクトの1セットの位置が指定されます。

出力値のレベルが1つのみのSourceの例については、例9-4を参照してください。ネストされた出力値を持つSourceの例については、例9-5を参照してください。

単一の値セットを表すSourceの例として、MdmDimensiongetSourceメソッドによって戻されるもの(製品の値を表すMdmPrimaryDimensionなど)があります。そのSourceCursorを作成することによって、ValueCursorが戻されます。getCurrentValueメソッドをコールすることによって、ValueCursorの現在の位置の製品の値が戻されます。

例9-2では、製品の値を表すMdmLevelHierarchyであるmdmProdHierからSourceが取得されます。また、そのSource用のCursorが作成されます。例では、現在の位置が、ValueCursorの第5要素に設定されて、Cursorから製品の値が取得されます。その後、CursorManagerがクローズされます。例の中のdpは、DataProviderです。

例9-2 ValueCursorからの単一の値の取得

Source prodSource = mdmProdHier.getSource();
// Because prodSource is a primary Source, you do not need to
// commit the current Transaction.
CursorManager cursorMngr = dp.createCursorManager(prodSource);
Cursor prodCursor = cursorMngr.createCursor();
// Cast the Cursor to a ValueCursor.
ValueCursor prodValues = (ValueCursor) prodCursor;
// Set the position to the fifth element of the ValueCursor.
prodValues.setPosition(5);

// Product values are strings. Get the value at the current position.
String value = prodValues.getCurrentString();

// Do something with the value, such as display it.

// Close the CursorManager.
cursorMngr.close();

例9-3では、例9-2と同じCursorを使用します。例9-3では、do...whileループおよびValueCursornextメソッドを使用して、ValueCursorの位置を移動します。nextメソッドは有効な位置で開始し、Cursorにその他の位置がある場合はtrueを戻します。また、現在の位置から次の位置へ移動させます。

例では、位置が、ValueCursorの最初の位置に設定されています。例では各位置をループし、getCurrentValueメソッドを使用して、現在の位置の値を取得します。

例9-3 ValueCursorからのすべての値の取得

// prodValues is the ValueCursor for prodSource.
prodValues.setPosition(1);
do
{
  println(prodValues.getCurrentValue);
} while(prodValues.next());

CompoundCursorによって表される結果セットの値は、CompoundCursorの子ValueCursorオブジェクトに存在します。これらの値を取得するには、CompoundCursorから子ValueCursorオブジェクトを取得する必要があります。

CompoundCursorの例としては、(メジャーのディメンションから選択した値によって指定される)メジャーの値を表すSource用のCursorManagercreateCursorメソッドをコールすることによって戻されるものがあります。

例9-4では、unitsという名前のSourceを使用します。これは、販売台数を表すMdmMeasuregetSourceメソッドをコールすることによって生成されます。メジャーのディメンションは、製品、顧客、時間およびチャネルを表すMdmPrimaryDimensionオブジェクトです。この例では、これらのディメンションのデフォルト階層から選択した値を表すSourceオブジェクトが使用されます。該当するSourceオブジェクトの名前は、prodSelcustSeltimeSelおよびchanSelです。メジャーおよびディメンションの選択を表すSourceオブジェクトの作成については、ここでは示しません。

例9-4では、ディメンションの選択がメジャーに結合されます。この結果、unitsForSelectionsという名前のSourceが生成されます。unitsForSelectionsに対しunitsForSelCursorという名前のCompoundCursorが作成され、ベースValueCursorおよびCompoundCursorの出力が取得されます。この場合、各出力はValueCursorです。出力は、Listに戻されます。List内での出力の順序は、連続的な結合操作によって出力が出力のリストに追加された順序と逆になります。例の中のdpは、DataProviderです。

例9-4 CompoundCursorからのValueCursorオブジェクトの取得

Source unitsForSelections = units.join(prodSel)
                                 .join(custSel)
                                 .join(timeSel)
                                 .join(chanSel);
// Commit the current Transaction (code not shown).

// Create a Cursor for unitsForSelections.
CursorManager cursorMngr = dp.createCursorManager(unitsForSelections);
CompoundCursor unitsForSelCursor = (CompoundCursor)
                                    cursorMngr.createCursor();

// Get the base ValueCursor.
ValueCursor specifiedUnitsVals = unitsForSelCursor.getValueCursor();

// Get the outputs.
List outputs = unitsForSelCursor.getOutputs();
ValueCursor chanSelVals = (ValueCursor) outputs.get(0);
ValueCursor timeSelVals = (ValueCursor) outputs.get(1);
ValueCursor custSelVals = (ValueCursor) outputs.get(2);
ValueCursor prodSelVals = (ValueCursor) outputs.get(3);

// You can now get the values from the ValueCursor objects.
// When you have finished using the Cursor objects, close the CursorManager.
cursorMngr.close();

例9-5で使用するunitsメジャーは、例9-4と同じものですが、ディメンションの選択をメジャーに結合する方法は異なります。例9-5では、2つのディメンションの選択が結合されます。その後、結果は、単一のディメンションの選択をメジャーに結合することによって生成されたSourceに結合されます。その結果生成されたSourceunitsForSelections)では、問合せにネストされた出力が存在することが表されます。これは、問合せに2つ以上のレベルの出力があることを意味します。

したがって、この例でunitsForSelections用に作成されるCompoundCursorにも、ネストされた出力が存在します。CompoundCursorは、子ベースValueCursorを持ちます。また、その出力は、3つの子ValueCursorオブジェクトおよび1つの子CompoundCursorを持ちます。

例9-5では、チャネル・ディメンション値の選択(chanSel)が顧客ディメンション値の選択(custSel)に結合されます。その結果は、ベース値として顧客の値、出力値としてチャネルの値を持つSourcecustByChanSel)です。製品および時間の値の選択は、unitsに結合され、その後custByChanSelに結合されます。これによって生成される問合せは、unitsForSelectionsによって表されます。

例では、現行のTransactionをコミットし、unitsForSelectionsに対してunitsForSelCursorというCompoundCursorを作成します。

例では、ベースValueCursorおよびCompoundCursorからの出力が取得されます。例の中のdpは、DataProviderです。

例9-5 ネストされた出力を持つCompoundCursorからの値の取得

Source custByChanSel = custSel.join(chanSel);
Source unitsForSelections = units.join(prodSel)
                                 .join(timeSel)
                                 .join(custByChanSel);
// Commit the current Transaction (code not shown).

// Create a Cursor for unitsForSelections.
CursorManager cursorMngr = dp.createCursorManager(unitsForSelections);
Cursor unitsForSelCursor = cursorMngr.createCursor();

// Send the Cursor to a method that does different operations
// depending on whether the Cursor is a CompoundCursor or a
// ValueCursor.
printCursor(unitsForSelCursor);
cursorMngr.close();
// The remaining code of someMethod is not shown.

// The following code is in from the CursorPrintWriter class.
// The printCursor method has a do...while loop that moves through the positions
// of the Cursor passed to it. At each position, the method prints the number of
// the iteration through the loop and then a colon and a space. The output
// object is a PrintWriter. The method calls the private _printTuple method and
// then prints a new line. A "tuple" is the set of output ValueCursor values
// specified by one position of the parent CompoundCursor. The method prints one
// line for each position of the parent CompoundCursor.
private void printCursor(Cursor rootCursor)
{
  int i = 1;
  do
  {
     print(i++ + ": ");
     _printTuple(rootCursor);
     println();
     flush();
  } while(rootCursor.next());
}

// If the Cursor passed to the _printTuple method is a ValueCursor, then
// the method prints the value at the current position of the ValueCursor.
// If the Cursor passed in is a CompoundCursor, then the method gets the
// outputs of the CompoundCursor and iterates through the outputs,
// recursively calling itself for each output. The method then gets the
// base ValueCursor of the CompoundCursor and calls itself again.
private void _printTuple(Cursor cursor)
{
  if(cursor instanceof CompoundCursor)
  {
    CompoundCursor compoundCursor = (CompoundCursor)cursor;
    // Put an open parenthesis before the value of each output.
    print("(");
    Iterator iterOutputs = compoundCursor.getOutputs().iterator();
    Cursor output = (Cursor)iterOutputs.next();
    _printTuple(output);
    while(iterOutputs.hasNext())
    {
      // Put a comma after the value of each output.
      print(",");
      _printTuple((Cursor)iterOutputs.next());
    }
    // Put a comma after the value of the last output.
    print(",");
    // Get the base ValueCursor.
    _printTuple(compoundCursor.getValueCursor());

    // Put a close parenthesis after the base value to indicate
    // the end of the tuple.
    print(")");
  }
  else if(cursor instanceof ValueCursor)
  {
    ValueCursor valueCursor = (ValueCursor) cursor;
    if (valueCursor.hasCurrentValue())
      print(valueCursor.getCurrentValue());
    else                       // If this position has a null value.
      print("NA");
  }
}

様々なデータ表示のためのCompoundCursorのナビゲート

CompoundCursorのメソッドを使用すると、CompoundCursor構造を簡単に移動(ナビゲート)して、CompoundCursorの子孫ValueCursorから値を取得できます。OLAPの多次元問合せからのデータは、通常、クロス集計形式または表やグラフとして表示されます。

複数の行および列にデータを表示するには、表示の要件に応じて、様々なレベルのCompoundCursorの位置をループします。表などの一部の表示方法の場合、親CompoundCursorの位置をループします。クロス集計などのその他の表示方法の場合、子Cursorオブジェクトの位置をループします。

問合せの結果を表ビューで表示する場合、各行が出力の各ValueCursorおよびベースValueCursorからの値で構成されるため、最上位(ルート・レベル)のCompoundCursorの位置を決定して、その位置で反復します。例9-6は、ある時点での結果セットの抜粋です。製造コストの値を持つメジャーに基づいた問合せを表すSource用のCursorが作成されます。そのメジャーのディメンションは、製品ディメンションおよび時間ディメンションです。プライマリSourceオブジェクトの作成、およびディメンションの導出された選択については、ここでは示しません。

例では、ディメンション値の選択を表すSourceオブジェクトが、メジャーを表すSourceに結合されます。現行のTransactionがコミットされ、次にCursorが作成され、それがCompoundCursorにキャストされます。この例では、CompoundCursorの位置が設定され、CompoundCursorの12の位置で反復し、それらの位置で指定された値が出力されます。DataProviderdpです。

例9-6 表ビュー用のナビゲート

Source unitPriceByMonth = unitPrice.join(productSel)
                                   .join(timeSel);
// Commit the current Transaction (code not shown).

// Create a Cursor for unitPriceByMonth.
CursorManager cursorMngr = dp.createCursorManager(unitPriceByMonth);
CompoundCursor rootCursor = (CompoundCursor) cursorMngr.createCursor();

// Determine a starting position and the number of rows to display.
int start = 7;
int numRows =12;

println("Month     Product     Unit Price");
println("-------   --------   ----------");

// Iterate through the specified positions of the root CompoundCursor.
// Assume that the Cursor contains at least (start + numRows) positions.
for(int pos = start; pos < start + numRows; pos++)
{
   // Set the position of the root CompoundCursor.
   rootCursor.setPosition(pos);
  // Print the local values of the output and base ValueCursors.
  // The getLocalValue method gets the local value from the unique
  // value of a dimension element.
  String timeValue = ((ValueCursor)rootCursor.getOutputs().get(0))
                     .getCurrentString();
  String timeLocVal = getLocalValue(timeValue);
  String prodValue = ((ValueCursor)rootCursor.getOutputs().get(1))
                     .getCurrentString();
  String prodLocVal = getLocalValue(prodValue);
  Object price = rootCursor.getValueCursor().getCurrentValue();
  println(timeLocVal + "   " + prodLocVal + "   " +  price);
};
cursorMngr.close();

問合せの時間の選択に8つの値(2001年および2002年の各四半期の最初の月など)が存在し、製品の選択に3つの値が存在する場合、unitPriceByMonth問合せの結果セットには、24の位置が存在します。例9-6では、次のような表が表示されます。この表には、CompoundCursorの7〜18の位置によって指定された値が含まれます。

Month     Product    Unit Price
-------   --------   ----------
2001.07   ENVY ABM   2892.18
2001.07   ENVY EXE   3155.91
2001.07   ENVY STD   2505.57
2001.10   ENVY ABM   2856.86
2001.10   ENVY EXE   3105.53
2001.10   ENVY STD   2337.3
2002.01   ENVY ABM   2896.77
2002.01   ENVY EXE   3008.95
2002.01   ENVY STD   2140.71
2002.04   ENVY ABM   2880.39
2002.04   ENVY EXE   2953.96
2002.04   ENVY STD   2130.88

例9-7では、例9-6と同じ問合せを使用します。クロス集計ビューでは、第1行が列ヘッダーです。この例でのヘッダーは、prodSelからの値です。prodSelの出力は、速く変化する出力です。これは、prodSelディメンションの選択が、メジャーをディメンションの選択に結合する操作によって生成される出力のリストの最後の出力であるためです。残りの行は、行ヘッダーで始まります。行ヘッダーは、遅く変化する出力のtimeSelからの値です。列ヘッダーの下に表示される残りの行の位置には、ディメンション値のセットによって指定されたunitPriceの値が含まれます。クロス集計ビューで問合せの結果を表示するには、最上位のCompoundCursorの子の位置で反復します。

DataProviderdpです。

例9-7 単一ページのクロス集計ビュー用のナビゲート

Source unitPriceByMonth = unitPrice.join(productSel)
                                   .join(timeSel);
// Commit the current Transaction (code not shown).

// Create a Cursor for unitPriceByMonth.
CursorManager cursorMngr = dp.createCursorManager(unitPriceByMonth);
CompoundCursor rootCursor = (CompoundCursor) cursorMngr.createCursor();

// Get the outputs and the ValueCursor.
List outputs = rootCursor.getOutputs();
// The first output has the values of timeSel, the slower varying output.
ValueCursor rowCursor = (ValueCursor) outputs.get(0);
// The second output has the faster varying values of productSel.
ValueCursor columnCursor = (ValueCursor) outputs.get(1);
// The base ValueCursor has the values from unitPrice.
ValueCursor unitPriceValues = rootCursor.getValueCursor();

// Display the values as a crosstab.
println("                     PRODUCT");
println("          ---------------------------------");
print("Month     ");
do
{
  String value = ((ValueCursor) columnCursor).getCurrentString();
  print(getContext().getLocalValue(value) + "    ");
} while (columnCursor.next());
println("\n-------   --------    --------    --------");

// Reset the column Cursor to its first element.
columnCursor.setPosition(1);

do
{
  // Print the row dimension values.
  String value = ((ValueCursor) rowCursor).getCurrentString();
  print(getContext().getLocalValue(value) + "    ");
  // Loop over columns.
  do
  {
    // Print data value.
    print(unitPriceValues.getCurrentValue() + "     ");
  } while (columnCursor.next());

  println();

  // Reset the column Cursor to its first element.
  columnCursor.setPosition(1);
  } while (rowCursor.next());

cursorMngr.close();

次のクロス集計ビューは、unitPriceByMonth問合せによって指定された結果セットからの値を表示したものです。最初の行は、製品の値が右側の3つの列に含まれていることを示します。3行目は、最初の列に月の値が含まれ、その右にある3つの各列に製品の値が含まれていることを示します。残りの行では、左の列に月の値が、その横には指定された月および製品のunitsメジャーのデータ値が示されています。

                     PRODUCT
          ---------------------------------
Month     ENVY ABM    ENVY EXE    ENVY STD
-------   --------    --------    --------
2001.01    3042.22     3223.28     2426.07
2001.04    3026.12     3107.65     2412.42
2001.07    2892.18     3155.91     2505.57
2001.10    2856.86     3105.53     2337.30
2002.01    2896.77     3008.95     2140.71
2002.04    2880.39     2953.96     2130.88
2002.07    2865.14     3002.34     2074.56
2002.10    2850.88     2943.96     1921.62

例9-8では、販売台数のメジャーに基づいたSourceを作成します。メジャーのディメンションは、顧客、製品、時間およびチャネルです。それらのディメンション用のSourceオブジェクトは、ディメンション値の選択を表します。これらのSourceオブジェクトの作成については、ここでは示しません。

ディメンションの選択をメジャーのSourceに結合することによって作成される問合せは、その出力値によって指定される販売台数の値を表します。

この例では、問合せのCursorが作成され、そのCursorprintAsCrosstabメソッドに送られます。このメソッドは、Cursorからの値をクロス集計に出力します。このメソッドは、ページ値、列値および行値を出力する別のメソッドをコールします。

Cursorの最も速く変化する出力は、製品の選択で、3つの値(製品項目ENVY ABM、ENVY EXEおよびENVY STD)が存在します。製品の値はクロス集計の列ヘッダーです。2番目に速く変化する出力は、顧客の選択で、3つの値(顧客COMP SERV TOK、COMP WHSE LONおよびCOMP WHSE SD)が存在します。これらの3つの値は行ヘッダーです。ページ・ディメンションには、時間の3つの値(月2000.01、2000.02および2000.03)およびチャネルの1つの値(直販チャネルを表すDIR)が選択されています。

DataProviderdpです。getLocalValueメソッドは、一意のディメンション値からローカル値を取得します。

例9-8 複数ページのクロス集計ビュー用のナビゲート

// In someMethod.
Source unitsForSelections = units.join(prodSel)
                                 .join(custSel)
                                 .join(timeSel)
                                 .join(chanSel);
// Commit the current Transaction (code not shown).

// Create a Cursor for unitsForSelections.
CursorManager cursorMngr = dp.createCursorManager(unitsForSelections);
CompoundCursor unitsForSelCursor = (CompoundCursor) cursorMngr.createCursor();

// Send the Cursor to the printAsCrosstab method.
printAsCrosstab(unitsForSelCursor);

cursorMngr.close();
// The remainder of the code of someMethod is not shown.

private void printAsCrosstab(CompoundCursor rootCursor)
{
  List outputs = rootCursor.getOutputs();
  int nOutputs = outputs.size();

  // Set the initial positions of all outputs.
  Iterator outputIter = outputs.iterator();
  while (outputIter.hasNext())
    ((Cursor) outputIter.next()).setPosition(1);

  // The last output is fastest-varying; it represents columns.
  // The next to last output represents rows.
  // All other outputs are on the page.
  Cursor colCursor = (Cursor) outputs.get(nOutputs - 1);
  Cursor rowCursor = (Cursor) outputs.get(nOutputs - 2);
  ArrayList pageCursors = new ArrayList();
  for (int i = 0 ; i < nOutputs - 2 ; i++)
  {
    pageCursors.add(outputs.get(i));
  }

  // Get the base ValueCursor, which has the data values.
  ValueCursor dataCursor = rootCursor.getValueCursor();

  // Print the pages of the crosstab.
  printPages(pageCursors, 0, rowCursor, colCursor, dataCursor);
}

// Prints the pages of a crosstab.
private void printPages(List pageCursors, int pageIndex, Cursor rowCursor,
                        Cursor colCursor, ValueCursor dataCursor)
{
  // Get a Cursor for this page.
  Cursor pageCursor = (Cursor) pageCursors.get(pageIndex);

  // Loop over the values of this page dimension.
  do
  {
    // If this is the fastest-varying page dimension, print a page.
    if (pageIndex == pageCursors.size() - 1)
    {
      // Print the values of the page dimensions.
      printPageHeadings(pageCursors);

      // Print the column headings.
      printColumnHeadings(colCursor);

      // Print the rows.
      printRows(rowCursor, colCursor, dataCursor);

      // Print a couple of blank lines to delimit pages.
      println();
      println();
    }

    // If this is not the fastest-varying page, recurse to the
    // next fastest-varying dimension.
    else
    {
      printPages(pageCursors, pageIndex + 1, rowCursor, colCursor,
                 dataCursor);
    }
  } while (pageCursor.next());

  // Reset this page dimension Cursor to its first element.
  pageCursor.setPosition(1);
}

// Prints the values of the page dimensions on each page.
private void printPageHeadings(List pageCursors)
{
  // Print the values of the page dimensions.
  Iterator pageIter = pageCursors.iterator();
  while (pageIter.hasNext())
  {
    String value = ((ValueCursor) pageIter.next()).getCurrentString();
    println(getLocalValue(value));
  }
  println();
}

// Prints the column headings on each page.
private void printColumnHeadings(Cursor colCursor)
{
  do
  {
     print("\t");
     String value = ((ValueCursor) colCursor).getCurrentString();
     print(getLocalValue(value));
  } while (colCursor.next());
  println();
  colCursor.setPosition(1);
}

// Prints the rows of each page.
private void printRows(Cursor rowCursor, Cursor colCursor,
                       ValueCursor dataCursor)
{
  // Loop over rows.
  do
  {
    // Print row dimension value.
    String value = ((ValueCursor) rowCursor).getCurrentString();
    print(getLocalValue(value));
    print("\t");
    // Loop over columns.
    do
    {
      // Print data value.
      print(dataCursor.getCurrentValue());
      print("\t");
    } while (colCursor.next());
    println();

    // Reset the column Cursor to its first element.
    colCursor.setPosition(1);
  } while (rowCursor.next());

  // Reset the row Cursor to its first element.
  rowCursor.setPosition(1);
}

例9-8は、クロス集計として書式化された値を表示します。ディメンションのローカル値を識別するために、ページ・ヘッダー、列ヘッダーおよび行ヘッダーが表示されます。

Channel DIR
Month 2001.01
                           Product
                ------------------------------
Customer        ENVY ABM   ENVY EXE   ENVY STD
-------------   --------   --------   --------
COMP WHSE SD       0          0          1
COMP SERV TOK         2          4          2
COMP WHSE LON         1          1          2


Channel DIR
Month 2000.02
                           Product
                ------------------------------
Customer        ENVY ABM   ENVY EXE   ENVY STD
-------------   --------   --------   --------
COMP WHSE SD       1          1          1
COMP SERV TOK         5          6          6
COMP WHSE LON         1          2          2


Channel DIR
Month 2000.03
                           Product
                ------------------------------
Customer        ENVY ABM   ENVY EXE   ENVY STD
-------------   --------   --------   --------
COMP WHSE SD       0          2          2
COMP SERV TOK         2          0          2
COMP WHSE LON         0          2          3

Cursorの動作の指定

指定可能なCursorの動作は、次のとおりです。

Cursorの動作を指定するには、そのCursorに指定するCursorSpecificationのメソッドを使用します。CursorSpecificationは、CursorInfoSpecificationインタフェースを実装します。

SourceCursorSpecificationを作成するには、DataProvidercreateCursorInfoSpecificationメソッドをコールします。必要な特性を設定するには、CursorSpecificationのメソッドを使用します。次に、DataProviderの適切なcreateCursorManagerメソッドをコールしてCursorManagerを作成します。


注意:

エクステントあるいは(子Cursorの現在の値に対する)親Cursorの中での開始位置または終了位置を計算するように指定すると、非常にコストが高くなる場合があります。この計算には、多くの時間と計算リソースが使用される場合があります。アプリケーションに必要な場合にのみ、これらの計算を指定してください。

SourceCursorCursorSpecificationオブジェクトの関係、あるいはフェッチ・サイズ、エクステントまたはCursorの位置の概念の詳細は、第8章を参照してください。

例9-9では、SourceおよびSourceCompoundCursorSpecificationを作成した後に、最上位のCompoundCursorSpecificationから子CursorSpecificationオブジェクトを取得します。

例9-9 SourceのCursorSpecificationオブジェクトの取得

Source unitsForSelections = units.join(prodSel)
                                 .join(custSel)
                                 .join(timeSel)
                                 .join(chanSel);
// Commit the current Transaction (code not shown).

// Create a CompoundCursorSpecification for unitsForSelections.
CompoundCursorSpecification rootCursorSpec = (CompoundCursorSpecification)
                      dp.createCursorInfoSpecification(unitsForSelections);

// Get the ValueCursorSpecification for the base values.
ValueCursorSpecification baseValueSpec =
                        rootCursorSpec.getValueCursorSpecification();

// Get the ValueCursorSpecification objects for the outputs.
List outputSpecs = rootCursorSpec.getOutputs();
ValueCursorSpecification chanSelValCSpec =
                       (ValueCursorSpecification) outputSpecs.get(0);
ValueCursorSpecification timeSelValCSpec =
                       (ValueCursorSpecification) outputSpecs.get(1);
ValueCursorSpecification prodSelValCSpec =
                       (ValueCursorSpecification) outputSpecs.get(2);
ValueCursorSpecification custSelValCSpec =
                       (ValueCursorSpecification) outputSpecs.get(3);

CursorSpecificationオブジェクトを取得した後は、そのメソッドを使用して、それに対応しているCursorオブジェクトの動作を指定できます。

エクステントおよび値の開始/終了位置の計算

CompoundCursorによって取得された結果セットの表示を管理するために、その子Cursorコンポーネントのエクステントを把握しておくことが必要な場合があります。親CompoundCursorの中で子Cursorの現在の値が開始される位置も把握しておくことが必要な場合があります。子Cursorの現在の値のスパンを知っておくことが必要な場合もあります。スパンは、子Cursorの現在の値が占有する、親Cursorの位置の数です。値の終了位置から開始位置を引き、さらに1を引くことによって、スパンを計算できます。

Cursorのエクステント、あるいは親Cursorの中での値の開始位置または終了位置を取得する前に、Oracle OLAPでエクステントまたはそれらの位置の計算を行うように指定する必要があります。これらの計算の実行を指定するには、Cursor用のCursorSpecificationのメソッドを使用します。

例9-10では、Cursorのエクステントの計算を指定しています。この例では、例9-9CompoundCursorSpecificationを使用します。

例9-10 Cursorのエクステントの計算の指定

rootCursorSpec.setExtentCalculationSpecified(true);

CursorSpecificationのメソッドを使用すると、次の例に示すように、CursorSpecificationで、Cursorのエクステントを計算するように指定されているかどうかを判断できます。

boolean isSet = rootCursorSpec.isExtentCalculationSpecified();

例9-11では、親Cursorにおける子Cursorの現在の値の開始位置および終了位置の計算が指定されています。この例では、例9-9CompoundCursorSpecificationを使用します。

例9-11 親の中での開始/終了位置の計算の指定

// Get the List of CursorSpecification objects for the outputs.
// Iterate through the list, specifying the calculation of the extent
// for each output CursorSpecification.
Iterator iterOutputSpecs = rootCursorSpec.getOutputs().iterator();
while(iterOutputSpecs.hasNext())
{
  ValueCursorSpecification valCursorSpec = (ValueCursorSpecification)
                                            iterOutputSpecs.next();
  valCursorSpec.setParentStartCalculationSpecified(true);
  valCursorSpec.setParentEndCalculationSpecified(true);
}

CursorSpecificationのメソッドを使用すると、次の例に示すように、CursorSpecificationで、子Cursorの現在の値に対する、親Cursorの中での開始/終了位置を計算するように指定されているかどうかを判断できます。

Iterator iterOutputSpecs = rootCursorSpec.getOutputs().iterator();
ValueCursorSpecification valCursorSpec = (ValueCursorSpecification)
                                          iterOutputSpecs.next();
while(iterOutputSpecs.hasNext())
{
  if (valCursorSpec.isParentStartCalculationSpecified())
    // Do something.
  if (valCursorSpec.isParentEndCalculationSpecified())
    // Do something.
  valCursorSpec = (ValueCursorSpecification) iterOutputSpecs.next();
}

例9-12では、CompoundCursorの2つの出力に関して、(子Cursorの現在の値に対する)親CompoundCursorの中での位置のスパンが決定されます。この例では、例9-8unitForSelections Sourceを使用します。

例では、時間および製品の選択の現在の値の開始および終了位置が取得され、親Cursorの中でのこれらの値のスパンが計算されます。親は、ルートCompoundCursorです。DataProviderdpです。

例9-12 値の親の中での位置のスパンの計算

Source unitsForSelections = units.join(prodSel)
                                 .join(custSel)
                                 .join(timeSel)
                                 .join(chanSel);
// Commit the current Transaction (code not shown).

// Create a CompoundCursorSpecification for unitsForSelections.
CompoundCursorSpecification rootCursorSpec = (CompoundCursorSpecification)
                          dp.createCursorInfoSpecification(unitsForSelections);
// Get the CursorSpecification objects for the outputs.
List outputSpecs = rootCursorSpec.getOutputs();
ValueCursorSpecification timeSelValCSpec =
  (ValueCursorSpecification) outputSpecs.get(1); // Output for time.
ValueCursorSpecification prodSelValCSpec =
 (ValueCursorSpecification) outputSpecs.get(3);  // Output for product.

// Specify the calculation of the starting and ending positions.
timeSelValCSpec.setParentStartCalculationSpecified(true);
timeSelValCSpec.setParentEndCalculationSpecified(true);
prodSelValCSpec.setParentStartCalculationSpecified(true);
prodSelValCSpec.setParentEndCalculationSpecified(true);

// Create the CursorManager and the Cursor.
CursorManager cursorMngr = dp.createCursorManager(unitsForSelections,
                                                  100, rootCursorSpec);
CompoundCursor rootCursor = (CompoundCursor) cursorMngr.createCursor();

// Get the child Cursor objects.
ValueCursor baseValCursor = cursor.getValueCursor();
List outputs = rootCursor.getOutputs();
ValueCursor chanSelVals = (ValueCursor) outputs.get(0);
ValueCursor timeSelVals = (ValueCursor) outputs.get(1);
ValueCursor custSelVals = (ValueCursor) outputs.get(2);
ValueCursor prodSelVals = (ValueCursor) outputs.get(3);

// Set the position of the root CompoundCursor.
rootCursor.setPosition(15);

// Get the values at the current position and determine the span
// of the values of the time and product outputs.
print(promoSelVals.getCurrentValue() + ", ");
print(chanSelVals.getCurrentValue() + ", ");
print(timeSelVals.getCurrentValue() + ", ");
print(custSelVals.getCurrentValue() + ", ");
print(prodSelVals.getCurrentValue() + ", ");
println(baseValCursor.getCurrentValue());

// Determine the span of the values of the two fastest-varying outputs.
int span;
span = (prodSelVals.getParentEnd() - prodSelVals.getParentStart()) +1);
println("The span of " + prodSelVals.getCurrentValue() +
        " at the current position is " + span + ".")
span = (timeSelVals.getParentEnd() - timeSelVals.getParentStart()) +1);
println("The span of " + timeSelVals.getCurrentValue() +
        " at the current position is " + span + ".")
cursorMngr.close();

この例によって表示されるテキストは、次のとおりです。

CHANNEL_PRIMARY::CHANNEL::DIR, CALENDAR_YEAR::MONTH::2000.02,
SHIPMENTS::SHIP_TO::COMP SERV TOK, PRODUCT_PRIMARY::ITEM::ENVY STD, 6.0
The span of PRODUCT_PRIMARY::ITEM::ENVY STD at the current position is 1.
The span of CALENDAR_YEAR::MONTH::2000.02 at the current position is 9.

フェッチ・サイズの指定

1回のフェッチ操作中にOracle OLAPがクライアント・アプリケーションに送るCursorの要素の数は、そのCursor用に指定されたフェッチ・サイズによって異なります。デフォルトのフェッチ・サイズは100です。フェッチ・サイズを変更するには、SourceのルートCursorのフェッチ・サイズを設定します。

例9-13では、例9-9CompoundCursorSpecificationからデフォルトのフェッチ・サイズを取得します。この例では、Cursorを作成し、異なるフェッチ・サイズを設定してから、そのCursorのフェッチ・サイズを取得します。DataProviderdpです。

例9-13 フェッチ・サイズの指定

println("The default fetch size is "
         + rootCursorSpec.getDefaultFetchSize() + ".");
Source source = rootCursorSpec.getSource();
CursorManager cursorMngr = dp.createCursorManager(source);
Cursor rootCursor = cursorMngr.createCursor();
rootCursor.setFetchSize(10);
println("The fetch size is now " + rootCursor.getFetchSize()) + ".";

この例によって表示されるテキストは、次のとおりです。

The default fetch size is 100.
The fetch size is now 10.