java.sql package in JDBC provides Connection interface that encapsulates database connection functionality. Using Connection interface, you can fine tune the following operations :

1. Set optimal row pre-fetch value

2. Use Connection pool

3. Control transaction

4. Choose optimal isolation level

5. Close Connection when finished

Each of these operations effects the performance. We will walk through each operation one by one.

1. Set optimal row pre-fetch value

We have different approaches to establish a connection with the database, the first type of approach is :

1. DriverManager.getConnection(String url)

2. DriverManager.getConnection(String url, Properties props)

3. DriverManager.getConnection(String url, String user, String password)

4. Driver.connect(String url, Properties props)

When you use this approach, you can pass database specific information to the database by passing properties using Properties object to improve performance. For example, when you use oracle database you can pass default number of rows that must be pre-fetched from the database server and the default batch value that triggers an execution request. Oracle has default value as 10 for both properties. By increasing the value of these properties, you can reduce the number of database calls which in turn improves performance. The following code snippet illustrates this approach.

java.util.Properties props = new java.util.Properties();

props.put(”user”,”scott”);

props.put(”password”,”tiger”);

props.put(”defaultRowPrefetch”,”30″);

props.put(”defaultBatchValue”,”5″);

Connection con = DriverManger.getConnection(”jdbc:oracle:thin:@hoststring”, props);

You need to figure out appropriate values for above properties for better performance depending on application’s requirement. Suppose, you want to set these properties for search facility, you can increase defaultRowPrefetch so that you can increase performance significantly.

The second type of approach is to get connection from DataSource.

You can get the connection using javax.sql.DataSource interface. The advantage of getting connection from this approach is that the DataSource works with JNDI. The implementation of DataSource is done by vendor, for example you can find this feature in weblogic, websphere etc. The vendor simply creates DataSource implementation class and binds it to the JNDI tree. The following code shows how a vendor creates implementation class and binds it to JNDI tree.

DataSourceImpl dsi = new DataSourceImpl();

dsi.setServerName(”oracle8i”);

dsi.setDatabaseName(”Demo”);

Context ctx = new InitialContext();

ctx.bind(”jdbc/demoDB”, dsi);

This code registers the DataSourceImpl object to the JNDI tree, then the programmer can get the DataSource reference from JNDI tree without knowledge of the underlying technology.

Context ctx = new InitialContext();

DataSource ds = (DataSource)ctx.lookup(”jdbc/demoDB”);

Connection con = ds.getConnection();

By using this approach we can improve performance. Nearly all major vendor application servers like weblogic, webshpere implement the DataSource by taking connection from connection pool rather than a single connection every time. The application server creates connection pool by default. We will discuss the advantage of connection pool to improve performance in the next section.

2. Use Connection pool

Creating a connection to the database server is expensive. It is even more expensive if the server is located on another machine. Connection pool contains a number of open database connections with minimum and maximum connections, that means the connection pool has open connections between minimum and maximum number that you specify. The pool expands and shrinks between minimum and maximum size depending on incremental capacity. You need to give minimum, maximum and incremental sizes as properties to the pool in order to maintain that functionality. You get the connection from the pool rather directly .For example, if you give properties like min, max and incremental sizes as 3, 10 and 1 then pool is created with size 3 initially and if it reaches it’s capacity 3 and if a client requests a connection concurrently, it increments its capacity by 1 till it reaches 10 and later on it puts all its clients in a queue.

There are a few choices when using connection pool.

1. You can depend on application server if it supports this feature, generally all the application servers support connection pools. Application server creates the connection pool on behalf of you when it starts. You need to give properties like min, max and incremental sizes to the application server.

2. You can use JDBC 2.0 interfaces, ConnectionPoolDataSource and PooledConnection if your driver implements these interfaces

3. Or you can create your own connection pool if you are not using any application server or JDBC 2.0 compatible driver.

By using any of these options, you can increase performance significantly. You need to take care of properties like min, max and incremental sizes. The maximum number of connections to be given depends on your application’s requirement that means how many concurrent clients can access your database and also it depends up on your database’s capability to provide maximum number of connections.

3. Control transaction

In general, transaction represents one unit of work or bunch of code in the program that executes in it’s entirety or none at all. To be precise, it is all or no work. In JDBC, transaction is a set of one or more Statements that execute as a single unit.

java.sql.Connection interface provides some methods to control transaction they are

public interface Connection {

boolean getAutoCommit();

void setAutoCommit(boolean autocommit);

void commit();

void rollback();

}

JDBC’s default mechanism for transactions:

By default in JDBC transaction starts and commits after each statement’s execution on a connection. That is the AutoCommit mode is true. Programmer need not write a commit() method explicitly after each statement.

Obviously this default mechanism gives good facility for programmers if they want to execute a single statement. But it gives poor performance when multiple statements on a connection are to be executed because commit is issued after each statement by default, that in turn reduces performance by issuing unnecessary commits. The remedy is to flip it back to AutoCommit mode as false and issue commit() method after a set of statements execute, this is called as batch transaction. Use rollback() in catch block to rollback the transaction whenever an exception occurs in your program. The following code illustrates the batch transaction approach.

try{

connection.setAutoCommit(false);

PreparedStatement ps = connection.preareStatement( “UPDATE employee SET Address=? WHERE name=?”);

ps.setString(1,”Austin”);

ps.setString(2,”RR”);

ps.executeUpdate();

PreparedStatement ps1 = connection.prepareStatement( “UPDATE account SET salary=? WHERE name=?”);

ps1.setDouble(1, 5000.00);

ps1.setString(2,”RR”);

ps1.executeUpdate();

connection.commit();

connection.setAutoCommit(true);

}catch(SQLException e){ connection.rollback();}

finally{

if(ps != null){ ps.close();}

if(ps1 != null){ps1.close();}

if(connection != null){connection.close();}

}

This batch transaction gives good performance by reducing commit calls after each statement’s execution.