JBoss.orgCommunity Documentation

Chapter 2. JDBC and Transactions

2.1. Using the transactional JDBC driver
2.1.1. Managing transactions
2.1.2. Restrictions
2.2. Transactional drivers
2.2.1. Loading drivers
2.3. Connections
2.3.1. JDBC
2.3.2. XADataSources
2.3.3. Using the connection
2.3.4. Connection pooling
2.3.5. Reusing connections
2.3.6. Terminating the transaction
2.3.7. AutoCommit
2.3.8. Setting isolation levels

JBossJTA supports construction of both local and distributed transactional applications which access databases using the JDBC APIs. JDBC supports two-phase commit of transactions, and is similar to the XA X/Open standard. JBossTS provides JDBC support in package com.arjuna.ats.jdbc. A list of the tested drivers is available from the JBossTS website.

Only use the transactional JDBC support provided in package com.arjuna.ats.jdbc when you are using JBossTS outside of an application server, such as JBoss Application Server, or another container. Otherwise, use the JDBC support provided by your application server or container.

The approach JBossJTA takes for incorporating JDBC connections within transactions is to provide transactional JDBC drivers as conduits for all interactions. These drivers intercept all invocations and ensure that they are registered with, and driven by, appropriate transactions. The driver com.arjuna.ats.jdbc.TransactionalDriver handles all JDBC drivers, implementing the java.sql.Driver interface. If the database is not transactional, ACID properties cannot be guaranteed.

Because JBossJTA provides JDBC connectivity via its own JDBC driver, application code can support transactions with relatively small code changes. Typically, the application programmer only needs to start and terminate transactions.

The JBossJTA driver accepts the following properties, all located in class com.arjuna.ats.jdbc.TransactionalDriver.

username

the database username

password

the database password

createDb

creates the database automatically if set to true. Not all JDBC implementations support this.

dynamicClass

specifies a class to instantiate to connect to the database, instead of using JNDI.

JDBC connections are created from appropriate DataSources. Connections which participate in distributed transactions are obtained from XADataSources. When using a JDBC driver, JBossJTA uses the appropriate DataSource whenever a connection to the database is made. It then obtains XAResources and registers them with the transaction via the JTA interfaces. The transaction service uses these XAResources when the transaction terminates in order to drive the database to either commit or roll back the changes made via the JDBC connection.

JBossJTA JDBC support can obtain XADataSources through the Java Naming and Directory Interface (JNDI) or dynamic class instantiation.

A JDBC driver can use arbitrary DataSources without having to know specific details about their implementations, by using JNDI. A specific DataSource or XADataSource can be created and registered with an appropriate JNDI implementation, and the application, or JDBC driver, can later bind to and use it. Since JNDI only allows the application to see the DataSource or XADataSource as an instance of the interface (e.g., javax.sql.XADataSource) rather than as an instance of the implementation class (e.g., com.mydb.myXADataSource), the application is not tied at build-time to only use a specific implementation.

For the TransactionalDriver class to use a JNDI-registered XADataSource, you need to create the XADataSource instance and store it in an appropriate JNDI implementation. Details of how to do this can be found in the JDBC tutorial available at the Java web site.

Example 2.4. Storing a datasource in a JNDI implementation

XADataSource ds = MyXADataSource();

Hashtable env = new Hashtable();
String initialCtx = PropertyManager.getProperty("Context.INITIAL_CONTEXT_FACTORY");
env.put(Context.INITIAL_CONTEXT_FACTORY, initialCtx);
initialContext ctx = new InitialContext(env);
ctx.bind("jdbc/foo", ds);
 

The Context.INITIAL_CONTEXT_FACTORY property is the JNDI way of specifying the type of JNDI implementation to use.

The application must pass an appropriate connection URL to the JDBC driver:



          Properties dbProps = new Properties();
dbProps.setProperty(TransactionalDriver.userName, "user");
dbProps.setProperty(TransactionalDriver.password, "password");
// the driver uses its own JNDI context info, remember to set it up:
jdbcPropertyManager.propertyManager.setProperty(
                                                "Context.INITIAL_CONTEXT_FACTORY", initialCtx);
jdbcPropertyManager.propertyManager.setProperty(
                                                "Context.PROVIDER_URL", myUrl);
TransactionalDriver arjunaJDBCDriver = new TransactionalDriver();
Connection connection = arjunaJDBCDriver.connect("jdbc:arjuna:jdbc/foo", dbProps);

The JNDI URL must be pre-pended with jdbc:arjuna: in order for the TransactionalDriver to recognize that the DataSource must participate within transactions and be driven accordingly.


Once the connection is established, all operations on the connection are monitored by JBossJTA. you do not need to use the transactional connection within transactions. If a transaction is not present when the connection is used, then operations are performed directly on the database.

You can use transaction timeouts to automatically terminate transactions if a connection is not terminated within an appropriate period.

You can use JBossJTA connections within multiple transactions simultaneously. An example would be different threads, with different notions of the current transaction. JBossJTA does connection pooling for each transaction within the JDBC connection. Although multiple threads may use the same instance of the JDBC connection, internally there may be a separate connection for each transaction. With the exception of method close, all operations performed on the connection at the application level are only performed on this transaction-specific connection.

JBossJTA automatically registers the JDBC driver connection with the transaction via an appropriate resource. When the transaction terminates, this resource either commits or rolls back any changes made to the underlying database via appropriate calls on the JDBC driver.

Once created, the driver and any connection can be used in the same way as any other JDBC driver or connection.