7 TransactionProviderの使用方法
この章では、Oracle OLAP Java APIのTransaction
およびTransactionProvider
インタフェースについて説明し、アプリケーションでこれらのインタフェースの実装を使用する方法について説明します。 DataProvider
からTransactionProvider
を取得します。 TransactionProvider
のcommitCurrentTransaction
メソッドを使用して、メタデータ・オブジェクトをデータベースの永続ストレージに保存します。 また、派生したSource
を作成した後、Source
のCursor
を作成する前に、そのメソッドを使用します。 Transaction
をメタデータ・オブジェクトの作成後にコミットする例については、「メタデータとアナリティク・ワークスペースの作成」を参照してください。
この章では、次の項目について説明します。
7.1 トランザクションでのメタデータ・オブジェクトまたは問合せの作成について
Oracle OLAP Java APIは、トランザクション処理を行います。 問合せのSource
オブジェクトまたはメタデータ・オブジェクトの作成は、Transaction
のコンテキスト内で実行されます。 TransactionProvider
は、アプリケーションにTransaction
オブジェクトを提供し、それらのTransaction
オブジェクトをコミットまたは破棄します。
TransactionProvider
によって、次のことが保証されます。
-
Transaction
は他のTransaction
オブジェクトから分離されています。Transaction
で実行される操作は、他のTransaction
オブジェクトには表示されず、影響を受けません。 -
Transaction
の操作が失敗した場合、操作の影響は取り消されます(Transaction
はロールバックされます)。 -
完了した
Transaction
の結果は存続します。
DataProvider
とUserSession
を作成すると、セッションには最初にTransaction
がありません。 セッション内の最初のTransaction
はルートTransaction
です。 TransactionProvider
のcreateRootTransaction
メソッドを呼び出して、明示的にルートTransaction
を作成することができます。 明示的に作成しないと、Oracle OLAPは、MdmObject
または派生Source
を初めて作成または変更するときに、ルートTransaction
を自動的に作成します。 MdmObject
に永続的な変更を加えるには、変更を加えたルートのTransaction
をコミットする必要があります。
シングル・ユーザー・アプリケーションでは、明示的にルートTransaction
を作成する必要はありません。 複数のルートTransaction
オブジェクトを作成する機能は、マルチスレッド、中間層アプリケーションで使用するために提供されています。 アプリケーションが複数のルートTransaction
オブジェクトを使用する場合、アプリケーションが1つのルートTransaction
で行った変更は、アプリケーションが別のルートTransaction
で行った変更によって上書きされます。 アプリケーションがコミットした最後のルートTransaction
で行われた変更は、永続的な変更です。
自分またはOracle OLAPが最初のルートTransaction
を作成するときは、current Transaction
です。 別のルートTransaction
を作成すると、現在のTransaction
になります。
Oracle OLAPは、Source
オブジェクトまたは子Transaction
オブジェクトをルートTransaction
の下に作成するときに、他のTransaction
オブジェクトを作成します。 Oracle DatabaseのルートTransaction
をコミットして、セッション内の任意のTransaction
で作成したメタデータ・オブジェクトを永続ストレージに追加する必要があります。
別のSource
のメソッドを呼び出すことによって派生したSource
を作成すると、派生したSource
が現在のTransaction
のコンテキストで作成されます。 Source
は、作成するTransaction
のactiveまたはそのTransaction
の子Transaction
です。
TransactionProvider
のメソッドを呼び出すことによって、現在のTransaction
を取得または設定したり、子Transaction
を開始したりすることができます。 子Transaction
では、たとえばディメンション要素の選択を変更するか、または親Transaction
で作成したTemplate
の状態を変更する、データに対して異なる数学的またはアナリティク的操作を実行することによって、問合せを変更できます。 親Transaction
内でTemplate
で生成されたSource
で指定されたデータと、子Transaction
内でTemplate
によって生成されたSource
で指定されたデータを表示することにより、アプリケーションのエンド・ユーザーに、問合せを変更したり同じデータ・セットに対する異なる操作の結果を表示したりすることを簡単にできます。
7.1.1 Transactionオブジェクトのタイプ
OLAP Java APIには、次の2つのタイプのTransaction
オブジェクトが存在します。
-
read
Transaction
。 最初は、現在のTransaction
はreadTransaction
です。 読取りTransaction
は、Cursor
を作成してOracle OLAPからデータをフェッチする場合に必要です。Cursor
オブジェクトの詳細については、「問合せ結果の取得」を参照してください。 -
write
Transaction
。 書込みTransaction
は、導出Source
の作成またはTemplate
の状態の変更を行う場合に必要です。 派生Source
の作成の詳細については、「ソース・オブジェクトの理解」を参照してください。Template
オブジェクトの詳細については、「動的問合せの作成」を参照してください。
初期読み込みTransaction
では、派生Source
を作成するか、Template
オブジェクトの状態を変更すると、子書き込みTransaction
が自動的に生成されます。 その子Transaction
が現在のTransaction
になります。
その後、導出Source
をもう1つ作成するか、またはTemplate
の状態を再度変更した場合、その操作は同じ書込みTransaction
で実行されます。 同じ書込みTransaction
で、導出Source
オブジェクトをいくつでも作成でき、Template
の状態も何回でも変更できます。 これらのSource
オブジェクト、またはTemplate
によって生成されたSource
を使用して、複雑な問合せを定義することができます。
派生Source
で指定された結果セットをフェッチするためにCursor
を作成する前に、Source
を子書き込みTransaction
から親read Transaction
に移動する必要があります。 これを行うには、Transaction
をコミットする必要があります。
7.1.2 Transactionのコミット
子Transaction
で作成したSource
を親のTransaction
に移動するには、TransactionProvider
のcommitCurrentTransaction
メソッドを呼び出します。 子をコミットするとTransaction
と書き込まれ、Transaction
という子で作成したSource
が親のTransaction
を読み込みます。 子Transaction
が消え、親Transaction
が現在のTransaction
になります。 Source
は、現行の読取りTransaction
でアクティブであるため、そのSourceのCursor
を作成できます。
例7-1 現行のTransactionのコミット
この例では、commit()
は現在のTransaction
をコミットするメソッドです。 例の中のdp
は、DataProvider
です。
private void commit() { try { (dp.getTransactionProvider()).commitCurrentTransaction(); } catch (Exception ex) { System.out.println("Could not commit the Transaction. " + ex); } }
7.1.3 TransactionおよびTemplateオブジェクト
現在のTransaction
の取得と設定、子Transaction
の開始、およびTransaction
のロールバックは、エンドユーザーが動的問合せの特定の状態から異なる選択を行うために使用する操作です。
エンド・ユーザーに同じ最初の問合せに基づいた代替を提供するには、次の手順を実行します。
-
親の
Transaction
にTemplate
を作成し、Template
の初期状態を設定します。 -
Template
によって生成されたSource
を取得し、Cursor
を作成して結果セットを取得し、Cursor
から値を取得して、結果をエンド・ユーザーに表示します。 -
子
Transaction
を開始して、Template
の状態を変更します。 -
子
Transaction
でTemplate
によって作成されたSource
を取得します。Cursor
を作成して、取得した値を表示します。
その後、最初のTemplate
の状態を2番目のものと置換できます。2番目の状態を廃棄して、1番目のものを保持することもできます。
7.1.4 子Transactionの開始
子の読取りTransaction
を開始するには、使用中のTransactionProvider
のbeginSubtransaction
メソッドをコールします。 子がTransaction
を読み込んだ場合、Template
の状態を変更すると、子書き込みTransaction
が自動的に開始されます。 書き込みTransaction
は、子Transaction
の子です。
Template
によって生成されたSource
で指定されたデータを取得するには、Transaction
を親の読み取りTransaction
にコミットします。 その後、Cursor
を作成してデータをフェッチできます。 Template
の変更後の状態は、元の親では参照できません。 変更された状態は、子がTransaction
を親のread Transaction
に読み込むまでコミットするまで親に表示されません。
子がTransaction
を読み始めた後、その子のTransaction
、または最初の親Transaction
の孫を読み込むことができます。 子および孫Transaction
オブジェクトの作成方法の例については、例7-3を参照してください。
7.1.5 Transactionのロールバック
使用中のTransactionProvider
のrollbackCurrentTransaction
メソッドをコールすることによって、Transaction
をロールバック(取消し)できます。 Transaction
をロールバックすると、そのTransaction
中に行った変更が破棄され、Transaction
が消滅します。
Transaction
をロールバックする前に、そのTransaction
で作成したCursorManager
オブジェクトをすべてクローズする必要があります。 Transaction
をロールバックした後、作成したSource
オブジェクトまたはTransaction
で行ったTemplate
状態の変更は無効になります。 そのSource
オブジェクト用に作成したすべてのCursor
も無効になります。
Transaction
をロールバックすると、そのTransaction
をコミットできません。 同様に、Transaction
をコミットした後は、それをロールバックすることはできません。
例7-2 Transactionのロールバック
この例では、「動的問合せの作成」で説明されているTopBottomTemplate
クラスとSingleSelectionTemplate
クラスを使用します。 TopBottomTemplate
およびSingleSelectionTemplate
オブジェクトの作成では、この例では「例10-4」に表示されるコードと同じコードが使用されています。 この例には、そのコードは表示されていません。 TopBottomTemplate
の状態を設定します。 これは、TopBottomTemplate
の異なる状態を設定した子Transaction
を開始してから、子Transaction
をロールバックします。 println
メソッドは、CursorPrintWriter
オブジェクトを介してテキストを表示し、getContext
メソッドは、Cursor
オブジェクトを作成し、その値をCursorPrintWriter
で表示するメソッドを持つContext11g
オブジェクトを取得します。 CursorPrintWriter
およびContext11g
クラスは、このマニュアルのサンプル・プログラムで使用されています。
// The current Transaction is a read Transaction, t1. // Create a TopBottomTemplate using a hierarchy of the PRODUCT_AWJ dimension // as the base and dp as the DataProvider. TopBottomTemplate topNBottom = new TopBottomTemplate(prodHier, dp); // Changing the state of a Template requires a write Transaction, so a // write child Transaction, t2, is automatically started. topNBottom.setTopBottomType(TopBottomTemplate.TOP_BOTTOM_TYPE_TOP); topNBottom.setN(10); topNBottom.setCriterion(singleSelections.getSource()); // Get the TransactionProvider and commit the Transaction t2. TransactionProvider tp = dp.getTransactionProvider(); try { tp.commitCurrentTransaction(); // t2 disappears } catch(Exception e) { println("Cannot commit the Transaction. " + e); } // The current Transaction is now t1. // Get the dynamic Source produced by the TopBottomTemplate. Source result = topNBottom.getSource(); // Create a Cursor and display the results println("\nThe current state of the TopBottomTemplate" + "\nproduces the following values:\n"); getContext().displayTopBottomResult(result); // Start a child Transaction, t3. It is a read Transaction. tp.beginSubtransaction(); // t3 is the current Transaction // Change the state of topNBottom. Changing the state requires a // write Transaction so Transaction t4 starts automatically. topNBottom.setTopBottomType(TopBottomTemplate.TOP_BOTTOM_TYPE_BOTTOM); topNBottom.setN(15); // Commit the Transaction. try { tp.commitCurrentTransaction(); // t4 disappears } catch(Exception e) { println("Cannot commit the Transaction. " + e); } // Create a Cursor and display the results. // t3 is the current Transaction println("\nIn the child Transaction, the state of the" + "\nTopBottomTemplate produces the following values:\n"); getContext().displayTopBottomResult(result); // The displayTopBottomResult method closes the CursorManager for the // Cursor created in t3. // Undo t3, which discards the state of topNBottom that was set in t4. tp.rollbackCurrentTransaction(); // t3 disappears // Transaction t1 is now the current Transaction and the state of // topNBottom is the one defined in t2. // To show the current state of the TopNBottom template Source, commit // the Transaction, create a Cursor, and display the Cursor values. try { tp.commitCurrentTransaction(); } catch(Exception e) { println("Cannot commit the Transaction. " + e); } println("\nAfter rolling back the child Transaction, the state of" + "\nthe TopBottomTemplate produces the following values:\n"); getContext().displayTopBottomResult(result);
この例では、次の出力が生成されます。
The current state of the TopBottomTemplate produces the following values: 1. PRODUCT_PRIMARY::TOTAL_PRODUCT::TOTAL 2. PRODUCT_PRIMARY::CLASS::SFT 3. PRODUCT_PRIMARY::FAMILY::ACC 4. PRODUCT_PRIMARY::CLASS::HRD 5. PRODUCT_PRIMARY::FAMILY::MOD 6. PRODUCT_PRIMARY::FAMILY::OS 7. PRODUCT_PRIMARY::FAMILY::DISK 8. PRODUCT_PRIMARY::ITEM::MOUSE PAD 9. PRODUCT_PRIMARY::ITEM::OS 1 USER 10. PRODUCT_PRIMARY::ITEM::DLX MOUSE In the child Transaction, the state of the TopBottomTemplate produces the following values: 1. PRODUCT_PRIMARY::ITEM::EXT CD ROM 2. PRODUCT_PRIMARY::ITEM::OS DOC ITA 3. PRODUCT_PRIMARY::ITEM::OS DOC SPA 4. PRODUCT_PRIMARY::ITEM::INT CD USB 5. PRODUCT_PRIMARY::ITEM::ENVY EXT KBD 6. PRODUCT_PRIMARY::ITEM::19 SVGA 7. PRODUCT_PRIMARY::ITEM::OS DOC FRE 8. PRODUCT_PRIMARY::ITEM::OS DOC GER 9. PRODUCT_PRIMARY::ITEM::ENVY ABM 10. PRODUCT_PRIMARY::ITEM::INT CD ROM 11. PRODUCT_PRIMARY::ITEM::ENVY EXE 12. PRODUCT_PRIMARY::ITEM::OS DOC KAN 13. PRODUCT_PRIMARY::ITEM::ENVY STD 14. PRODUCT_PRIMARY::ITEM::1GB USB DRV 15. PRODUCT_PRIMARY::ITEM::SENT MM After rolling back the child Transaction, the state of the TopBottomTemplate produces the following values: 1. PRODUCT_PRIMARY::TOTAL_PRODUCT::TOTAL 2. PRODUCT_PRIMARY::CLASS::SFT 3. PRODUCT_PRIMARY::FAMILY::ACC 4. PRODUCT_PRIMARY::CLASS::HRD 5. PRODUCT_PRIMARY::FAMILY::MOD 6. PRODUCT_PRIMARY::FAMILY::OS 7. PRODUCT_PRIMARY::FAMILY::DISK 8. PRODUCT_PRIMARY::ITEM::MOUSE PAD 9. PRODUCT_PRIMARY::ITEM::OS 1 USER 10. PRODUCT_PRIMARY::ITEM::DLX MOUSE
7.2 TransactionProviderオブジェクトの使用方法
Oracle OLAP Java APIでは、DataProvider
がTransactionProvider
インタフェースの実装を提供します。 TransactionProvider
によって、アプリケーションにTransaction
オブジェクトが提供されます。
「"トランザクションのコミット"」で説明されているように、commitCurrentTransaction
メソッドを使用して、子で作成した派生Source
を、親のTransaction
で表示されるTransaction
に書き込みます。 その後、そのSource
用のCursor
を作成できます。
アプリケーションでTemplate
オブジェクトを使用している場合は、TransactionProvider
の他のメソッドを使用して次の操作を行うこともできます。
-
子
Transaction
を開始します。 -
保存するために、現行の
Transaction
を取得します。 -
現行の
Transaction
を以前に保存したものに設定します。 -
現在の
Transaction
をロールバックまたは元に戻し、Transaction
で行われた変更を破棄します。Transaction
がロールバックされると、それは無効であり、コミットできません。Transaction
がコミットされると、ロールバックできません。Transaction
のSource
のCursor
を作成した場合は、Transaction
をロールバックする前にCursorManager
を閉じる必要があります。
例7-3では、Transaction
オブジェクトを使用して動的問合せを変更する例を示します。 「例7-2」と同様に、この例ではTopBottomTemplate
とSingleSelectionTemplate
オブジェクトを作成するために「例10-4」と同じコードを使用しています。 この例には、そのコードは表示されていません。
Transaction
オブジェクトを追跡するのに役立つように、この例では、getCurrentTransaction
メソッドへの呼び出しで、さまざまなTransaction
オブジェクトを保存しています。 この例では、tp
オブジェクトはTransactionProvider
です。 println
メソッドはCursorPrintWriter
を介してテキストを表示し、getContext
メソッドはCursor
オブジェクトを作成するメソッドを持つContext11g
オブジェクトを取得し、CursorPrintWriter
を介してそれらの値を表示します。 commit
メソッドは「例7-1」のメソッドです。
例7-3 子Transactionオブジェクトの使用方法
// The parent Transaction is the current Transaction at this point. // Save the parent read Transaction as parentT1. Transaction parentT1 = tp.getCurrentTransaction(); // Get the dynamic Source produced by the TopBottomTemplate. Source result = topNBottom.getSource(); // Create a Cursor and display the results. println("\nThe current state of the TopBottomTemplate" + "\nproduces the following values:\n"); getContext().displayTopBottomResult(result); // Begin a child Transaction of parentT1. tp.beginSubtransaction(); // This is a read Transaction. // Save the child read Transaction as childT2. Transaction childT2 = tp.getCurrentTransaction(); // Change the state of the TopBottomTemplate. This starts a // write Transaction, a child of the read Transaction childT2. topNBottom.setN(12); topNBottom.setTopBottomType(TopBottomTemplate.TOP_BOTTOM_TYPE_BOTTOM); // Save the child write Transaction as writeT3. Transaction writeT3 = tp.getCurrentTransaction(); // Commit the write Transaction writeT3. commit(); // The commit moves the changes made in writeT3 into its parent, // the read Transaction childT2. The writeT3 Transaction // disappears. The current Transaction is now childT2 // again but the state of the TopBottomTemplate has changed. // Create a Cursor and display the results of the changes to the // TopBottomTemplate that are visible in childT2. try { println("\nIn the child Transaction, the state of the" + "\nTopBottomTemplate produces the following values:\n"); getContext().displayTopBottomResult(result); } catch(Exception e) { println("Cannot display the results of the query. " + e); } // Begin a grandchild Transaction of the initial parent. tp.beginSubtransaction(); // This is a read Transaction. // Save the grandchild read Transaction as grandchildT4. Transaction grandchildT4 = tp.getCurrentTransaction(); // Change the state of the TopBottomTemplate. This starts another // write Transaction, a child of grandchildT4. topNBottom.setTopBottomType(TopBottomTemplate.TOP_BOTTOM_TYPE_TOP); // Save the write Transaction as writeT5. Transaction writeT5 = tp.getCurrentTransaction(); // Commit writeT5. commit(); // Transaction grandchildT4 is now the current Transaction and the // changes made to the TopBottomTemplate state are visible. // Create a Cursor and display the results visible in grandchildT4. try { println("\nIn the grandchild Transaction, the state of the" + "\nTopBottomTemplate produces the following values:\n"); getContext().displayTopBottomResult(result); } catch(Exception e) { println(""Cannot display the results of the query. " + e); } // Commit the grandchild into the child. commit(); // Transaction childT2 is now the current Transaction. // Instead of preparing and committing the grandchild Transaction, // you could rollback the Transaction, as in the following // method call: // rollbackCurrentTransaction(); // If you roll back the grandchild Transaction, then the changes // you made to the TopBottomTemplate state in the grandchild // are discarded and childT2 is the current Transaction. // Commit the child into the parent. commit(); // Transaction parentT1 is now the current Transaction. Again, // you can roll back the childT2 Transaction instead of committing it. // If you do so, then the changes that you made in childT2 are discarded. // The current Transaction is be parentT1, which has the original state // of the TopBottomTemplate, without any of the changes made in the // grandchild or the child transactions.
例7-3の出力は、次のようになります。
The current state of the TopBottomTemplate produces the following values: 1. PRODUCT_PRIMARY::TOTAL_PRODUCT::TOTAL 2. PRODUCT_PRIMARY::CLASS::SFT 3. PRODUCT_PRIMARY::FAMILY::ACC 4. PRODUCT_PRIMARY::CLASS::HRD 5. PRODUCT_PRIMARY::FAMILY::MOD 6. PRODUCT_PRIMARY::FAMILY::OS 7. PRODUCT_PRIMARY::FAMILY::DISK 8. PRODUCT_PRIMARY::ITEM::MOUSE PAD 9. PRODUCT_PRIMARY::ITEM::OS 1 USER 10. PRODUCT_PRIMARY::ITEM::DLX MOUSE In the child Transaction, the state of the TopBottomTemplate produces the following values: 1. PRODUCT_PRIMARY::ITEM::EXT CD ROM 2. PRODUCT_PRIMARY::ITEM::OS DOC ITA 3. PRODUCT_PRIMARY::ITEM::OS DOC SPA 4. PRODUCT_PRIMARY::ITEM::INT CD USB 5. PRODUCT_PRIMARY::ITEM::ENVY EXT KBD 6. PRODUCT_PRIMARY::ITEM::19 SVGA 7. PRODUCT_PRIMARY::ITEM::OS DOC FRE 8. PRODUCT_PRIMARY::ITEM::OS DOC GER 9. PRODUCT_PRIMARY::ITEM::ENVY ABM 10. PRODUCT_PRIMARY::ITEM::INT CD ROM 11. PRODUCT_PRIMARY::ITEM::ENVY EXE 12. PRODUCT_PRIMARY::ITEM::OS DOC KAN In the grandchild Transaction, the state of the TopBottomTemplate produces the following values: 1. PRODUCT_PRIMARY::TOTAL_PRODUCT::TOTAL 2. PRODUCT_PRIMARY::CLASS::SFT 3. PRODUCT_PRIMARY::FAMILY::ACC 4. PRODUCT_PRIMARY::CLASS::HRD 5. PRODUCT_PRIMARY::FAMILY::MOD 6. PRODUCT_PRIMARY::FAMILY::OS 7. PRODUCT_PRIMARY::FAMILY::DISK 8. PRODUCT_PRIMARY::ITEM::MOUSE PAD 9. PRODUCT_PRIMARY::ITEM::OS 1 USER 10. PRODUCT_PRIMARY::ITEM::DLX MOUSE 11. PRODUCT_PRIMARY::ITEM::LT CASE 12. PRODUCT_PRIMARY::ITEM::56KPS MODEM