16.6.4 Database access
The Java Database Connectivity (JDBC) API provides a vendor-independent mechanism to access relational databases from Java. However, obtaining and closing a connection to a database can be a relatively expensive exercise, so the concept of connection pools has been introduced. When a database operation is to be performed, a connection can be obtained from the pool, which contains a defined number of connections to the database that have already been established. When the connection is closed, it is returned to the pool and made available for reuse. Using connection pooling can significantly reduce the overhead of obtaining a database connection. However, the connection pool is accessed via a datasource. References to the datasource are obtained by performing a lookup via the JNDI. This lookup is an expensive operation, so it is good practice to perform the lookup once and cache the result for reuse.
JDBC resources should always be released once they are no longer required. This includes java.sql.ResultSet, java.sql.Statement and java.sql.Connection objects, which should be closed in that order. The code to close the resources should be placed in a finally block to ensure that it is executed even when an exception condition occurs. Failure to properly close resources can cause memory leaks, and can cause slow response due to threads having to wait for a connection to become available from the pool. Since database connections in the pool are a limited resource, they should be returned to the pool once they are no longer required.
If an application repeatedly executes the same query, but with different input parameters, then performance can be improved by using a java.sql.PreparedStatement instead of java.sql.Statement.
Turning off auto commit for read only operations may also increase performance.
To avoid having to retrieve and process large amounts of data, sometimes it is beneficial to use database stored procedures for implementing some of the application logic. Alternatively, in some cases calls to the database can be minimized by using a single statement that returns multiple result sets.
There are different types of JDBC drivers available, some written in pure Java and others that are native. Although use of a native driver can reduce portability, performance may be better with a native driver.