0% found this document useful (0 votes)
128 views

Using JDBC and Data Sources

The document discusses using JDBC and data sources with Tomcat servlets and JSPs. It describes the problems with directly using JDBC in servlets, such as hardcoding database credentials and opening a new connection per request. It recommends using a connection pooling data source instead to avoid these issues and improve performance. It also provides sample code of a simple database servlet accessing rates data to demonstrate direct JDBC usage, and describes how this could be improved by using a data source.

Uploaded by

mhdridhuan
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
128 views

Using JDBC and Data Sources

The document discusses using JDBC and data sources with Tomcat servlets and JSPs. It describes the problems with directly using JDBC in servlets, such as hardcoding database credentials and opening a new connection per request. It recommends using a connection pooling data source instead to avoid these issues and improve performance. It also provides sample code of a simple database servlet accessing rates data to demonstrate direct JDBC usage, and describes how this could be improved by using a data source.

Uploaded by

mhdridhuan
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 6

Using JDBC and Data Sources

Tomcat servlets and JSPs use JDBC in the same manner as any other Java program. In many Java programs, it is normal to ask the user to provide a username and password for database access. With Web applications, you would typically use a single database account for all users and encode the account name and password within either the servlet or JSP, or encapsulate database access using a data source (see the section "Tomcat Data Sources") or a DAO (see the section "Data Access Objects (DAOs)"). You must then add the business logic of the application to enforce any user security authorization and ensure the data integrity of the database. The disadvantage to using JDBC from within a servlet is that the JDBC driver class, database connection string, user account name, and password are all hard-coded into the program. The hard-coded database details link the servlet to a specific database, complicating the move from a development environment (with test data) to a production environment (potentially using a different database supplier). Hard-coded details always reduce portability of code and should be avoided if at all possible. A common approach in reducing coupling of the servlet to the database is to provide the database connection parameters using servlet initialization parameters (see the <init-params> element discussion in Chapter 7, "The Web Application Environment"). If in the future you change database vendors, move the database to a new server, move the tables into a new database, change the username, or change the password, you can do so without modifying the Java servlet (or JSP). This is a good technique; but, as you will be shown, there are other performance problems that suggest you shouldn't use direct JDBC access from within a servlet. A connection pooling data source provides a solution to both the hard coding of database access details and the performance issues inherent in using direct database access. This chapter describes how to use Tomcat data sources after briefly discussing, and rejecting, using direct JDBC access from within a servlet. Before we describe direct JDBC access and data sources, you need a bit of background information about the database tables and sample data used for the examples.

The Sample Database


Continuing with the currency converter example application, the code examples in this chapter use a currency definition table called Currency and a database exchange rate table called Exchange. The Currency table has columns for the ISO 4217 currency name as well as the currency's ISO country name and ISO language. The Exchange table has columns that define the three-character ISO 4217 code for the currency to convert from (src) and to (dst). The rate column defines the appropriate exchange rate. The two tables can be created in any SQL database with the following SQL:
create table Currency( language varchar(2), country varchar(2),

name varchar(3) ); create table Exchange( src varchar(3), dst varchar(3), rate double );

You will need to create this table in your database and add some sample data in order to use the examples presented in this chapter. The following SQL will populate the table with suitable data:
insert insert insert insert insert insert insert insert insert insert insert insert insert insert insert insert into into into into into into into into into into into into into into into into Currency Currency Currency Currency Exchange Exchange Exchange Exchange Exchange Exchange Exchange Exchange Exchange Exchange Exchange Exchange values values values values values values values values values values values values values values values values ('en','CA', ('de','DE', ('en','GB', ('en','US', 'CAD'); 'EUR'); 'GBP'); 'USD'); 0.6955); 0.6376); 0.4344); 1.4376); 0.6246); 0.9166); 2.3019); 1.6011); 1.4676); 1.5685); 1.0909); 0.6813);

('CAD','EUR', ('CAD','USD', ('CAD','GBP', ('EUR','CAD', ('EUR','GBP', ('EUR','USD', ('GBP','CAD', ('GBP','EUR', ('GBP','USD', ('USD','CAD', ('USD','EUR', ('USD','GBP',

Tip - The CreateDB.java program available from the accompanying Web site for this book (browse to http://www.samspublishing.com and search for the ISBN 0-672-32439-3) can be used to create and populate the sample database tables.

Note - The examples in this chapter use the MySQL database available from http://www.mysql.com. MySQL is a popular, open source, SQL database available under the GNU General Public License (http://www.gnu.org/). Several JDBC drivers are available for MySQL. This chapter uses the MM.MySQL JDBC driver that is also provided under the GNU General Public License and is downloadable from the MySQL Web site. The MM.MySQL JDBC driver class name is org.gjt.mm.mysql.Driver. The examples use a JDBC connect string of jdbc:mysql://localhost/test to access the MySQL test database, which has been configured with a user account called root, password secret.

Now that you've finished the database configuration, let's take a closer look at using databases with Tomcat.

Direct JDBC Database Access


Any JDBC-compliant database can be used with Tomcat provided the necessary supporting classes are available. If the JDBC driver for a database is provided as a JAR file, this JAR file must be added to the <CATALINA_HOME>/common/lib directory; otherwise, the Tomcat 4.1 class loader will not be able to load the driver.

Note - The restriction of placing JDBC driver JAR files in <CATALINA_HOME>/common/lib applies to the Tomcat 4.1 beta release. Under Tomcat 4.0, you may also store the JAR files in the WEB-INF/lib or <CATALINA_HOME>/lib directory.

A Simple Database Servlet


The first example program shown in Listing 9.1 is a simple servlet that uses a database to display the exchange rate for converting UK pounds sterling (GBP) to US dollars (USD). Listing 9.1 The Simple Database Program DatabaseRates.java
import import import import import import java.io.*; java.sql.*; javax.sql.*; javax.servlet.*; javax.servlet.http.*; java.util.*;

public class DatabaseRates extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); PrintWriter out = response.getWriter(); Connection con = null; out.println ("<HTML><HEAD><TITLE>Conversion Rates"); out.println ("</TITLE></HEAD><BODY>"); out.println("<H1>Conversion Rates</H1>");

try { Class.forName("org.gjt.mm.mysql.Driver"); con = DriverManager.getConnection("jdbc:mysql://localhost/test","root","secret"); PreparedStatement pstmt = con.prepareStatement("SELECT rate FROM Exchange WHERE src = ? and dst = ?"); pstmt.setString(1,"GBP"); pstmt.setString(2,"USD"); ResultSet results = pstmt.executeQuery(); if (!results.next()) throw new SQLException("Missing Exchange rate data row"); double rate = results.getDouble(1); out.println("GBP to USD rate = "+rate+"<BR>"); pstmt.setString(1,"EUR"); pstmt.setString(2,"USD"); results = pstmt.executeQuery(); if (!results.next()) throw new SQLException("Missing Exchange rate data row"); rate = results.getDouble(1); out.println("EUR to USD rate = "+rate+"<BR>"); } catch (Exception ex) { out.println("<H2>Exception Occurred</H2>"); out.println(ex); if (ex instanceof SQLException) { SQLException sqlex = (SQLException) ex; out.println("SQL state: "+sqlex.getSQLState()+"<BR>"); out.println("Error code: "+sqlex.getErrorCode()+"<BR>"); } } finally { try { con.close(); } catch (Exception ex) {} } out.println ("</BODY></HTML>"); } }

y y y y

Post a comment Email Article Print Article Share Articles

Note - The error handling in Listing 9.1 and all other examples in this chapter is designed to aid development and debugging. Chapter 12, "Error Handling," discusses techniques for incorporating user-friendly error handling for a live application.

Although the example in Listing 9.1 works and is thread-safe, there are a large number of problems:

y y y

The JDBC driver, database, username, and password are hard-coded into the program. Every HTTP request must open a new connection to the database. The database access code and the HTML presentation code are inextricably intermixed within the servlet.

As previously discussed, hard-coded database details always reduce portability of code and should be avoided if at all possible. Opening a database connection for every request will result in slower performance and may overload the database server because creating new client connections is a resource-intensive operation. In addition, as you have already been shown, the mixing of business logic and data presentation in a single class is a sign of poor system design and makes code maintenance a nightmare. Each of the problems just identified can be resolved using standard tools and design techniques as discussed later in this chapter.

A Bad Example Servlet


Before studying the correct approach to database access using data sources, a common technique suggested by some online tutorials and textbooks will be examined and rejected due to the complications inherent in the approach. In order to improve performance, you might think of moving the database connection code into the HttpServlet.init() method as follows:
public class DatabaseRates extends HttpServlet implements SingleThreadModel { Connection con; PreparedStatement pstmt ; public void init() throws ServletException { try { Class.forName("org.gjt.mm.mysql.Driver"); con = DriverManager.getConnection("jdbc:mysql://localhost/test","root","secret"); pstmt = con.prepareStatement("SELECT rate FROM Exchange WHERE src = ? and dst = ?"); } catch (SQLException ex) { throw new ServletException("Cannot create database connection",ex); } } ...

This is a technique you should not adopt. By attempting to improve performance in this manner, you create a whole range of other potential problems:
y

The Connection and PreparedStatement instance variables are not multithreadsafe, and the servlet must now implement the SingleThreadModel, which will degrade servlet performance and scalability.

The database connection is kept open for the lifetime of the servlet instance and this may affect database performance and scalability. If you adopt the same approach for many servlets, you will use up large numbers of database connections for servlets that are idle for a lot of the time. You may even have to reconfigure your database to support an unusually large numbers of connections. A database may time out a connection that is kept open for too long or one that remains idle for specified period of time. If this happens, you will have to add code to your servlet to deal with a closed connection, further complicating the logic of your servlet.

You can address these problems by using the servlet init() method to cache the exchange rate in an instance variable when the servlet is first accessed. All subsequent accesses will use the cached rate rather than access the database. But this approach cannot handle the real-world situation where the exchange rate varies over time. To solve this problem, the servlet must periodically update the cached exchange rate from the master value stored in the database. You then have the problem of deciding on a suitable algorithm for updating the cached exchange rate and adding additional database access code. This adds complications to the servlet that can be avoided simply by using connection pooling.

You might also like