Oracle8i JDBC Developer's Guide and Reference Release 3 (8.1.7) Part Number A83724-01 |
Library | Service | Contents | Index

## Implementing a Distributed Transaction

This section provides an example of how to implement a distributed transaction using Oracle XA functionality.

### Summary of Imports for Oracle XA

You must import the following for Oracle XA functionality:

    import oracle.jdbc.xa.OracleXid;
    import oracle.jdbc.xa.OracleXAException;
    import oracle.jdbc.pool.*;
    import oracle.jdbc.xa.client.*;
    import javax.transaction.xa.*;

The `oracle.jdbc.pool` package has classes for connection pooling functionality, some of which are subclassed by XA-related classes.

In addition, if the code will run inside an Oracle database and access that database for SQL operations, you must import the following:

    import oracle.jdbc.xa.server.*;

(And if you intend to access only the database in which the code runs, you would not need the `oracle.jdbc.xa.client` classes.)

The `client` and `server` packages each have versions of the `OracleXADataSource`, `OracleXAConnection`, and `OracleXAResource` classes. Abstract versions of these three classes are in the top-level `oracle.jdbc.xa` package.

### Oracle XA Code Sample

This example uses a two-phase distributed transaction with two transaction branches, each to a separate database.

Note that for simplicity, this example combines code that would typically be in a middle tier with code that would typically be in a transaction manager (such as the XA resource method invocations and the creation of transaction IDs).

For brevity, the specifics of creating transaction IDs (in the `createID()` method) and performing SQL operations (in the `doSomeWork1()` and `doSomeWork2()` methods) are not shown here. The complete sample is in "XA with Two-Phase Commit Operation--XA4.java".

For another complete sample, showing how to use XA resource functionality to suspend and resume a transaction, see "XA with Suspend and Resume--XA2.java".

This example executes the following sequence:

1. Start transaction branch #1.

2. Start transaction branch #2.

3. Execute DML operations on branch #1.

4. Execute DML operations on branch #2.

5. End transaction branch #1.

6. End transaction branch #2.

7. Prepare branch #1.

8. Prepare branch #2.

9. Commit branch #1.

10. Commit branch #2.

        // You need to import the java.sql package to use JDBC
        import java.sql.*;
        import javax.sql.*;
        import oracle.jdbc.driver.*;
        import oracle.jdbc.pool.*;
        import oracle.jdbc.xa.OracleXid;
        import oracle.jdbc.xa.OracleXAException;
        import oracle.jdbc.xa.client.*;
        import javax.transaction.xa.*;

        class XA4
        {
          public static void main (String args [])
               throws SQLException
          {

            try
            {
                String URL1 = "jdbc:oracle:oci8:@";
                String URL2 ="jdbc:oracle:thin:@(description=(address=(host=dlsun991)
                             (protocol=tcp)(port=5521))(connect_data=(sid=rdbms2)))";

                DriverManager.registerDriver(new OracleDriver());

                // You can put a database name after the @ sign in the connection URL.
                Connection conna =
                  DriverManager.getConnection (URL1, "scott", "tiger");

                // Prepare a statement to create the table
                Statement stmta = conna.createStatement ();

                Connection connb =
                  DriverManager.getConnection (URL2, "scott", "tiger");

                // Prepare a statement to create the table
                Statement stmtb = connb.createStatement ();

                try
                {
                  // Drop the test table
                  stmta.execute ("drop table my_table");
                }
                catch (SQLException e)
                {
                  // Ignore an error here
                }

                try
                {
                  // Create a test table
                  stmta.execute ("create table my_table (col1 int)");
                }
                catch (SQLException e)
                {
                  // Ignore an error here too
                }

                try
                {
                  // Drop the test table
                  stmtb.execute ("drop table my_tab");
                }
                catch (SQLException e)
                {
                  // Ignore an error here
                }

                try
                {
                  // Create a test table
                  stmtb.execute ("create table my_tab (col1 char(30))");
                }
                catch (SQLException e)
                {
                  // Ignore an error here too
                }

                // Create XADataSource instances and set properties.
                OracleXADataSource oxds1 = new OracleXADataSource();
                oxds1.setURL("jdbc:oracle:oci8:@");
                oxds1.setUser("scott");
                oxds1.setPassword("tiger");

                OracleXADataSource oxds2 = new OracleXADataSource();

                oxds2.setURL("jdbc:oracle:thin:@(description=(address=(host=dlsun991)
                           (protocol=tcp)(port=5521))(connect_data=(sid=rdbms2)))");
                oxds2.setUser("scott");
                oxds2.setPassword("tiger");

                // Get XA connections to the underlying data sources
                XAConnection pc1  = oxds1.getXAConnection();
                XAConnection pc2  = oxds2.getXAConnection();

                // Get the physical connections
                Connection conn1 = pc1.getConnection();
                Connection conn2 = pc2.getConnection();

                // Get the XA resources
                XAResource oxar1 = pc1.getXAResource();
                XAResource oxar2 = pc2.getXAResource();

                // Create the Xids With the Same Global Ids
                Xid xid1 = createXid(1);
                Xid xid2 = createXid(2);

                // Start the Resources
                oxar1.start (xid1, XAResource.TMNOFLAGS);
                oxar2.start (xid2, XAResource.TMNOFLAGS);

                // Execute SQL operations with conn1 and conn2
                doSomeWork1 (conn1);
                doSomeWork2 (conn2);

                // END both the branches -- IMPORTANT
                oxar1.end(xid1, XAResource.TMSUCCESS);
                oxar2.end(xid2, XAResource.TMSUCCESS);

                // Prepare the RMs
                int prp1 =  oxar1.prepare (xid1);
                int prp2 =  oxar2.prepare (xid2);

                System.out.println("Return value of prepare 1 is " + prp1);
                System.out.println("Return value of prepare 2 is " + prp2);

                boolean do_commit = true;

                if (!((prp1 == XAResource.XA_OK) || (prp1 == XAResource.XA_RDONLY)))
                   do_commit = false;

                if (!((prp2 == XAResource.XA_OK) || (prp2 == XAResource.XA_RDONLY)))
                   do_commit = false;

               System.out.println("do_commit is " + do_commit);
                System.out.println("Is oxar1 same as oxar2 ? " + oxar1.isSameRM(oxar2));

                if (prp1 == XAResource.XA_OK)
                  if (do_commit)
                     oxar1.commit (xid1, false);
                  else
                     oxar1.rollback (xid1);

                if (prp2 == XAResource.XA_OK)
                  if (do_commit)
                     oxar2.commit (xid2, false);
                  else
                     oxar2.rollback (xid2);

                 // Close connections
                conn1.close();
                conn1 = null;
                conn2.close();
                conn2 = null;

                pc1.close();
                pc1 = null;
                pc2.close();
                pc2 = null;

                ResultSet rset = stmta.executeQuery ("select col1 from my_table");
                while (rset.next())
                  System.out.println("Col1 is " + rset.getInt(1));

                rset.close();
                rset = null;

                rset = stmtb.executeQuery ("select col1 from my_tab");
                while (rset.next())
                  System.out.println("Col1 is " + rset.getString(1));

                rset.close();
                rset = null;

                stmta.close();
                stmta = null;
                stmtb.close();
                stmtb = null;

                conna.close();
                conna = null;
                connb.close();
                connb = null;

            } catch (SQLException sqe)
            {
              sqe.printStackTrace();
            } catch (XAException xae)
            {
              if (xae instanceof OracleXAException) {
                System.out.println("XA Error is " +
                              ((OracleXAException)xae).getXAError());
                System.out.println("SQL Error is " +
                              ((OracleXAException)xae).getOracleError());
              }
            }
          }

          static Xid createXid(int bids)
            throws XAException
          {...Create transaction IDs...}

          private static void doSomeWork1 (Connection conn)
           throws SQLException
          {...Execute SQL operations...}

          private static void doSomeWork2 (Connection conn)
           throws SQLException
          {...Execute SQL operations...}

        }

| Copyright © 1996-2000, Oracle Corporation. All Rights Reserved. |
Library | Service | Contents | Index