Skip Headers
Oracle® OLAP Developer's Guide to the OLAP API
10g Release 2 (10.2)

Part Number B14347-01
Go to Documentation Home
Home
Go to Book List
Book List
Go to Table of Contents
Contents
Go to Index
Index
Go to Master Index
Master Index
Go to Feedback page
Feedback

Go to previous page
Previous
Go to next page
Next
View PDF

8 Using a TransactionProvider

This chapter describes the Oracle OLAP API Transaction and TransactionProvider interfaces and describes how you use implementations of those interfaces in an application. You must create a TransactionProvider before you can create a DataProvider, and you must use methods of the TransactionProvider to prepare and commit a Transaction before you can create a Cursor for a derived Source.

This chapter includes the following topics:

For the complete code for the examples in this chapter, see the example programs available from the Overview of the Oracle OLAP Java API Reference.

About Creating a Query in a Transaction

The Oracle OLAP API is transactional. Each step in creating a query occurs in the context of a Transaction. One of the first actions of an OLAP API application is to create a TransactionProvider. The TransactionProvider provides Transaction objects to the application.

The TransactionProvider ensures the following:

When you create a derived Source by calling a method of another Source, the derived Source is created in the context of the current Transaction. The Source is active in the Transaction in which you create it or in a child Transaction of that Transaction.

You get or set the current Transaction, or begin a child Transaction, by calling methods of a TransactionProvider. In a child Transaction you can alter the query, for example by changing the selection of dimension elements or by performing a different mathematical or analytical operation on the data, which changes the state of a Template that you created in the parent Transaction. By displaying the data specified by the Source produced by the Template in the parent Transaction and also displaying the data specified by the Source produced by the Template in the child Transaction, you can provide the end user of your application with the means of easily altering a query and viewing the results of different operations on the same set of data, or the same operations on different sets of data.

Types of Transaction Objects

The OLAP API has the following two types of Transaction objects:

  • A read Transaction. Initially, the current Transaction is a read Transaction. A read Transaction is required for creating a Cursor to fetch data from Oracle OLAP. For more information on Cursor objects, see Chapter 10.

  • A write Transaction. A write Transaction is required for creating a derived Source or for changing the state of a Template. For more information on creating a derived Source, see Chapter 6. For information on Template objects, see Chapter 11.

In the initial read Transaction, if you create a derived Source or if you change the state of a Template object, then a child write Transaction is automatically generated. That child Transaction becomes the current Transaction.

If you then create another derived Source or change the Template state again, that operation occurs in the same write Transaction. You can create any number of derived Source objects, or make any number of Template state changes, in that same write Transaction. You can use those Source objects, or the Source produced by the Template, to define a complex query.

Before you can create a Cursor to fetch the result set specified by a derived Source, you must move the Source from the child write Transaction into the parent read Transaction. To do so, you prepare and commit the Transaction.

Preparing and Committing a Transaction

To move a Source that you created in a child Transaction into the parent read Transaction, call the prepareCurrentTransaction and commitCurrentTransaction methods of the TransactionProvider. When you commit a child write Transaction, a Source you created in the child Transaction moves into the parent read Transaction. The child Transaction disappears and the parent Transaction becomes the current Transaction. The Source is active in the current read Transaction and you can therefore create a Cursor for it.

The following figure illustrates the process of moving a Source created in a child write Transaction into its parent read Transaction.

Figure 8-1 Committing a Write Transaction into Its Parent Read Transaction

Text description of commitwr.gif follows.
Description of "Figure 8-1 Committing a Write Transaction into Its Parent Read Transaction"

About Transaction and Template Objects

Getting and setting the current Transaction, beginning a child Transaction, and rolling back a Transaction are operations that you use to allow an end user to make different selections starting from a given state of a dynamic query.

To present the end user with alternatives based on the same initial query, you do the following:

  1. Create a Template in a parent Transaction and set the initial state for the Template.

  2. Get the Source produced by the Template, create a Cursor to retrieve the result set, get the values from the Cursor, and then display the results to the end user.

  3. Begin a child Transaction and modify the state of the Template.

  4. Get the Source produced by the Template in the child Transaction, create a Cursor, get the values, and display them.

You can then replace the first Template state with the second one or discard the second one and retain the first.

Beginning a Child Transaction

To begin a child read Transaction, call the beginSubtransaction method of the TransactionProvider you are using. In the child read Transaction, if you change the state of a Template, then a child write Transaction begins automatically. The write Transaction is a child of the child read Transaction.

To get the data specified by the Source produced by the Template, you prepare and commit the write Transaction into its parent read Transaction. You can then create a Cursor to fetch the data. The changed state of the Template is not visible in the original parent. The changed state does not become visible in the parent until you prepare and commit the child read Transaction into the parent read Transaction.

The following figure illustrates beginning a child read Transaction, creating Source objects in a write Transaction, and committing the write Transaction into its parent read Transaction. The figure then shows committing the child read Transaction into its parent read Transaction. In the figure, tp is the TransactionProvider.

Figure 8-2 Committing a Child Read Transaction into Its Parent Transaction

Text description of commitrd.gif follows.
Description of "Figure 8-2 Committing a Child Read Transaction into Its Parent Transaction"

After beginning a child read Transaction, you can begin a child read Transaction of that child, or a grandchild of the initial parent Transaction. For an example of creating child and grandchild Transaction objects, see Example 8-2.

About Rolling Back a Transaction

You roll back, or undo, a Transaction by calling the rollbackCurrentTransaction method of the TransactionProvider you are using. Rolling back a Transaction discards any changes that you made during that Transaction and makes the Transaction disappear.

Before rolling back a Transaction, you must close any CursorManager objects you created in that Transaction. After rolling back a Transaction, any Source objects that you created or Template state changes that you made in the Transaction are no longer valid. Any Cursor objects you created for those Source objects are also invalid.

Once you roll back a Transaction, you cannot prepare and commit that Transaction. Likewise, once you commit a Transaction, you cannot roll it back.

Example 8-1 Rolling Back a Transaction

The following example uses the TopBottomTemplate and SingleSelectionTemplate classes that are described in Chapter 11, "Creating Dynamic Queries". In creating the TopBottomTemplate and SingleSelectionTemplate objects, the example uses the same code that appears in Example 11-4, "Getting the Source Produced by the Template". Example 8-1 does not show that code. This example sets the state of the TopBottomTemplate. It begins a child Transaction that sets a different state for the TopBottomTemplate and then rolls back the child Transaction. The TransactionProvider is tp and context is an object that has methods that create Cursor objects and display their values.

// The current Transaction is a read Transaction, t1.
// Create a TopBottomTemplate using a hierarchy of the Product dimension
// as the base and dp as the DataProvider.
TopBottomTemplate topNBottom = new TopBottomTemplate(prodRollup, 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());

// Prepare and commit the Transaction t2.
try
{
  tp.prepareCurrentTransaction();
}
catch(NotCommittableException e)
{
  context.println("Cannot commit the Transaction. " + e);
}
tp.commitCurrentTransaction();           //t2 disappears

// 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 (these operations are
// performed by the context object).
context.println("\nThe current state of the TopBottomTemplate\n" +
                "produces the following values:\n");
context.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);

// Prepare and commit the Transaction.
try
{
  tp.prepareCurrentTransaction();
}
catch(NotCommittableException e)
{
  context.println("Cannot commit the Transaction. " + e);
}
tp.commitCurrentTransaction();           // t4 disappears

// Create a Cursor and display the results. // t3 is the current Transaction
context.println("\nIn the child Transaction, the state of the\n" +
                "TopBottomTemplate produces the following values:\n");
context.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,
// prepare and commit the Transaction, create a Cursor, and display
// its values.
try
{
  tp.prepareCurrentTransaction();
}
catch(NotCommittableException e)
{
  context.println("Cannot commit the Transaction. " + e);
}
tp.commitCurrentTransaction();

context.println("\nAfter rolling back the child Transaction, the state "
+ "of\nthe TopBottomTemplate produces the following "
+ "values:\n");
context.displayTopBottomResult(result);

Example 8-1 produces the following output.

The current state of the TopBottomTemplate
produces the following values:
 
1. PRODUCT_ROLLUP::TOTAL_PRODUCT::1
2. PRODUCT_ROLLUP::CLASS::3
3. PRODUCT_ROLLUP::FAMILY::7
4. PRODUCT_ROLLUP::CLASS::2
5. PRODUCT_ROLLUP::FAMILY::9
6. PRODUCT_ROLLUP::FAMILY::6
7. PRODUCT_ROLLUP::FAMILY::11
8. PRODUCT_ROLLUP::ITEM::30
9. PRODUCT_ROLLUP::ITEM::28
10. PRODUCT_ROLLUP::ITEM::47
 
In the child Transaction, the state of the
TopBottomTemplate produces the following values:
 
1. PRODUCT_ROLLUP::ITEM::36
2. PRODUCT_ROLLUP::ITEM::43
3. PRODUCT_ROLLUP::ITEM::44
4. PRODUCT_ROLLUP::ITEM::38
5. PRODUCT_ROLLUP::ITEM::22
6. PRODUCT_ROLLUP::ITEM::21
7. PRODUCT_ROLLUP::ITEM::42
8. PRODUCT_ROLLUP::ITEM::41
9. PRODUCT_ROLLUP::ITEM::15
10. PRODUCT_ROLLUP::ITEM::34
11. PRODUCT_ROLLUP::ITEM::14
12. PRODUCT_ROLLUP::ITEM::45
13. PRODUCT_ROLLUP::ITEM::13
14. PRODUCT_ROLLUP::ITEM::26
15. PRODUCT_ROLLUP::ITEM::18
 
After rolling back the child Transaction, the state of
the TopBottomTemplate produces the following values:
 
1. PRODUCT_ROLLUP::TOTAL_PRODUCT::1
2. PRODUCT_ROLLUP::CLASS::3
3. PRODUCT_ROLLUP::FAMILY::7
4. PRODUCT_ROLLUP::CLASS::2
5. PRODUCT_ROLLUP::FAMILY::9
6. PRODUCT_ROLLUP::FAMILY::6
7. PRODUCT_ROLLUP::FAMILY::11
8. PRODUCT_ROLLUP::ITEM::30
9. PRODUCT_ROLLUP::ITEM::28
10. PRODUCT_ROLLUP::ITEM::47

Getting and Setting the Current Transaction

You get the current Transaction by calling the getCurrentTransaction method of the TransactionProvider you are using, as in the following example.

Transaction t1 = getCurrentTransaction();

To make a previously saved Transaction the current Transaction, you call the setCurrentTransaction method of the TransactionProvider, as in the following example.

setCurrentTransaction(t1);

Using TransactionProvider Objects

In the Oracle OLAP API, the TransactionProvider interface is implemented by the ExpressTransactionProvider concrete class. Before you create a DataProvider, you must create a new instance of an ExpressTransactionProvider. You then pass that TransactionProvider to the DataProvider constructor. The TransactionProvider provides Transaction objects to your application.

As described in "Preparing and Committing a Transaction", you use the prepareCurrentTransaction and commitCurrentTransaction methods to make a derived Source that you created in a child write Transaction visible in the parent read Transaction. You can then create a Cursor for that Source.

If you are using Template objects in your application, then you might also use the other methods of TransactionProvider to do the following:

Example 8-2 demonstrates the use of Transaction objects to modify dynamic queries. Like Example 8-1, this example uses the same code to create TopBottomTemplate and SingleSelectionTemplate objects as does Example 11-4, "Getting the Source Produced by the Template". This example does not show that code.

To help track the Transaction objects, this example saves the different Transaction objects with calls to the getCurrentTransaction method. In the example, tp object is the TransactionProvider, and context is an object that has methods that create Cursor objects and display their values.

Example 8-2 Using Child Transaction Objects

// 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 (these operations are
// performed by the context object).
context.println("\nThe current state of the TopBottomTemplate\n" +
                "produces the following values:\n");
context.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();

// Prepare and commit the write Transaction writeT3.
try
{
  tp.prepareCurrentTransaction();
}
catch(NotCommittableException e)
{
  context.println("Cannot commit current Transaction. " + e);
}
tp.commitCurrentTransaction();

// 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
{
  context.println("\nIn the child Transaction, the state of the\n" +
                  "TopBottomTemplate produces the following values:\n");

  context.displayTopBottomResult(result);
}
catch(Exception e)
{
  context.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();

// Prepare and commit writeT5.
try
{
  tp.prepareCurrentTransaction();
}
catch(NotCommittableException e)
{
  context.println("Cannot commit current Transaction. " + e);
}
tp.commitCurrentTransaction();

// 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
{
  context.println("\nIn the grandchild Transaction, the state of the\n" +
                  "TopBottomTemplate produces the following values:\n");
  context.displayTopBottomResult(result);
}
catch(Exception e)
{
  context.println(""Cannot display the results of the query. " + e);
}

// Commit the grandchild into the child.
try
{
  tp.prepareCurrentTransaction();
}
catch(NotCommittableException e)
{
  context.println("Cannot commit current Transaction. " + e);
}
tp.commitCurrentTransaction();

// 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.
try
{
  tp.prepareCurrentTransaction();
}
catch(NotCommittableException e)
{
  context.println("Cannot commit the child Transaction. " + e);
}
tp.commitCurrentTransaction();

// Transaction parentT1 is now the current Transaction. Again,
// you can roll back the childT2 Transaction instead of
// preparing and committing it. If you do so, then the changes
// 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.

Example 8-2 produces the following output.

The current state of the TopBottomTemplate
produces the following values:
 
1. PRODUCT_ROLLUP::TOTAL_PRODUCT::1
2. PRODUCT_ROLLUP::CLASS::3
3. PRODUCT_ROLLUP::FAMILY::7
4. PRODUCT_ROLLUP::CLASS::2
5. PRODUCT_ROLLUP::FAMILY::9
6. PRODUCT_ROLLUP::FAMILY::6
7. PRODUCT_ROLLUP::FAMILY::11
8. PRODUCT_ROLLUP::ITEM::30
9. PRODUCT_ROLLUP::ITEM::28
10. PRODUCT_ROLLUP::ITEM::47
 
In the child Transaction, the state of the
TopBottomTemplate produces the following values:
 
1. PRODUCT_ROLLUP::ITEM::36
2. PRODUCT_ROLLUP::ITEM::43
3. PRODUCT_ROLLUP::ITEM::44
4. PRODUCT_ROLLUP::ITEM::38
5. PRODUCT_ROLLUP::ITEM::22
6. PRODUCT_ROLLUP::ITEM::21
7. PRODUCT_ROLLUP::ITEM::42
8. PRODUCT_ROLLUP::ITEM::41
9. PRODUCT_ROLLUP::ITEM::15
10. PRODUCT_ROLLUP::ITEM::34
11. PRODUCT_ROLLUP::ITEM::14
12. PRODUCT_ROLLUP::ITEM::45
 
In the grandchild Transaction, the state of the
TopBottomTemplate produces the following values:
 
1. PRODUCT_ROLLUP::TOTAL_PRODUCT::1
2. PRODUCT_ROLLUP::CLASS::3
3. PRODUCT_ROLLUP::FAMILY::7
4. PRODUCT_ROLLUP::CLASS::2
5. PRODUCT_ROLLUP::FAMILY::9
6. PRODUCT_ROLLUP::FAMILY::6
7. PRODUCT_ROLLUP::FAMILY::11
8. PRODUCT_ROLLUP::ITEM::30
9. PRODUCT_ROLLUP::ITEM::28
10. PRODUCT_ROLLUP::ITEM::47
11. PRODUCT_ROLLUP::ITEM::19
12. PRODUCT_ROLLUP::ITEM::24