| I l @ ve RuBoard |
Chapter 4. JDBC Best Practices
The JDBC API is the ideal interface for database access, independent of the constraints of any particular database engine. In theory, you can take your JDBC application and deploy it on any operating system within any application server talking to any relational database. In reality, however, it's easy for a programmer to write seemingly database-independent JDBC code that results in wildly different behavior on different database engines. In this chapter, I have compiled a list of best practices that can help ensure both database independence and optimal performance of your JDBC code. |
| I l @ ve RuBoard |
| I l @ ve RuBoard |
4.1 ConfigurationJDBC configuration has very little to do with programming, per se. Instead, JDBC configuration assists you in configuring your applications in their runtime environments. Through proper JDBC configuration, you can take advantage of many of the performance features of your database of choice without burdening your applications with proprietary code. Proper configuration provides your database engine of choice with all the information it needs to tailor itself to your application's needs. 4.1.1 Avoid Type 1 and Type 3 DriversSun classifies JDBC drivers into four categories, as shown in Table 4-1. Table 4-1. JDBC drivers
Most programmers learn JDBC using the JDBC-ODBC Bridge, which is a Type 1 JDBC driver. Nevertheless, the JDBC-ODBC Bridge is a
bridging driver
. In other words, it's a driver that
Though avoiding Type 1 and Type 3 drivers is a good rule of thumb, sometimes they cannot be avoided. Not all databases are supported by a Type 2 or Type 4 driver. For example, if you want an application to talk to Microsoft Access, you must use a Type 1 or Type 3 driver. 4.1.1.1 When to use a Type 1 or Type 3 driverYou should use a Type 1 driver under the following circumstances:
You should use a Type 3 driver when:
4.1.1.2 Choosing between Type 2 and Type 4 driversAs I just mentioned, you should always try to use a Type 2 or Type 4 driver whenever possible. The only time you should choose a Type 3 driver rather than a Type 2 driver is when your application requires portability. It never makes sense to use a Type 1 bridging driver instead of a Type 2 or Type 4 driver. That said, which is better, a Type 2 or a Type 4? This largely depends on how you intend to use it. The choice between Type 2 and Type 4 comes down to portability and an understanding of the underlying mechanics of the two drivers. Here are some guidelines:
4.1.2 Use DataSource Whenever PossibleIf you have a choice, you always should use javax.sql.DataSource to get a JDBC connection. Data sources, which were introduced with JDBC 2.0, make the job of configuring a database connection and connecting to a database nearly foolproof. Consider the following data source code fragment:
InitialContext ctx = new InitialContext( );
DataSource ds = (DataSource)ctx.lookup("dsname");
Connection conn = ds.getConnection( );
This code contains nothing proprietary, involves no parsing of configuration files, and uses no information dependent on the deployment environment other than a data source
Connection conn;
Class.forName("org.gjt.mm.mysql.Driver").newInstance( );
conn = DriverManager.getConnection("jdbc:mysql://carthage:/db", "user", "password");
This code is the simplest alternative to using a data source. However, the latter example is harder to read, contains proprietary code (i.e., specific reference to the Driver implementation class, which is the JDBC URL for a specific driver), and requires hard-coded information about the runtime environment (e.g., the host and database in the URL, the username, and the password). In short, you have to compile the DriverManager version for a specific target runtime environment.
To be fair, it is possible to achieve the same level of portability with the driver manager approach as with the data source approach. However, doing so makes your application code much more complex. In this case, you would have to
4.1.3 Leverage Proprietary Connection Properties
Java has conditioned us to embrace open, generic standards and shy away from
Every JDBC driver comes with a set of connection properties that allow you to specially configure it. Put another way, they allow you to tell the driver a bit about your application so that it can
The two most common
First, pass the system properties into the constructor of an InitialContext object:
InitialContext ctx = new InitialContext(System.getProperties( ));
DataSource ds = (DataSource)ctx.lookup("dsname");
Connection conn = ds.getConnection( );
Or, if you use the DriverManager class (see my earlier warning against this), pass the system properties hashtable into the getConnection( ) method: Connection conn = DriverManager.getConnection(url, System.getProperties( ));
You can then pass in JDBC connection properties by specifying them directly on the command line, configuring them
java -Duser=uid -Dpassword=pw -Dencoding=8859-1 -Dautocommit=true DBApp 4.1.4 Pool Database Connections
A sure way to bog down any JDBC application is to repeatedly open and close database connections. This problem is
Before JDBC 2.0, you had to write your own connection pooling support or look for a third-party tool. Put succinctly, connection pooling was a coding problem. Thanks to JDBC 2.0, however, connection pooling is now just a configuration issue. This means you simply have to convert your data source to a pooled data source; the code to access data from the connection remains the same, regardless of whether you use connection pooling. However, even though connection pooling is becoming more commonplace in JDBC code, it should still be included as a JDBC best practice.
How you configure your application to use a pooled connection depends on the environment in which you are running it. First, you must use a
DataSource
that supports connection pooling, which typically means obtaining an object that implements the
javax.sql.ConnectionPoolDataSource
interface. Your application then grabs its pooled connections from this data source. The only part that varies from one environment to the
Example 4-1 shows code used to obtain and release a pooled connection. Example 4-1. Obtaining and releasing a pooled database connection
import javax.sql.*;
import javax.naming.*;
public void connectToDatabase( ) {
try {
InitialContext ctx = new InitialContext(parms);
ConnectionPoolDataSource poolDataSource =
(ConnectionPoolDataSource)ctx.lookup(
cpsource);
poolDataSource.setLoginTimeout(30); // seconds
PooledConnection poolConnection =
poolDataSource.getPooledConnection( );
Connection connection = poolConnection.getConnection( );
// Do whatever you would typically do with the connection
// here.
} catch (Exception e) {
// Handle exceptions.
} finally {
connection.close( );
}
}
|
| I l @ ve RuBoard |