Sie sind auf Seite 1von 11

198 CHAPTER 7

Working with databases

7.3.1 Project overview


In this project we must build an application to support an upcoming JSP confer-
ence, which is being held in several major cities across the U.S. First, we must deter-
mine which conference (city) the user plans to attend and reserve a slot for him or
her, as seating is very limited. Secondly, we must also reserve a seat for the user on
one of the several shuttle buses which will transport participants from the airport to
the conference. The tricky part is making sure that once the user has secured a
ticket to the conference he or she doesn’t lose it to other users while picking a shut-
tle option. This becomes a very real possibility when you consider thousands of
users registering across the globe simultaneously.

7.3.2 Our database


Our database backend already exists and is populated with the relevant data in two
tables, CONFERENCES (table 7.2) and SHUTTLES (table 7.3). The tables are related
through their respective AIRPORT column, which holds the three-character identifier
for each airport associated with each conference city. Once the user has selected a
city, we can use the airport identifier to locate appropriate shuttle service.

Table 7.2 Schema for the Conferences table

Column Type
ID int
CITY varchar(80)
AIRPORT char(3)
SEATS int

Table 7.3 Schema for the Shuttles table

Column Type
ID int
AIRPORT char(3)
TIME time
SEATS int

7.3.3 Design overview


There are four basic steps in this process: picking a city, choosing a shuttle, review-
ing selections, and confirming the transaction. A user will be presented a list of
Example: JSP conference booking tool 199

cities where the conference will be held and may select any one of them where space
is available. Doing so should hold his or her seat in the database by starting a trans-
action. This will ensure that the user doesn’t lose his or her seat while selecting the
shuttle in the second step. The third and fourth steps in the process are to have the
user review his or her selections and confirm them—committing the changes to the
database—or abort the process, rolling back the selections to free them for other,
less fickle attendees.
To maintain a transaction across
several pages like this we’ll need to use
JSP’s session management capabilities
to store our connection to the data-
base, which we’ll wrap in the Connec-
tionBean we built earlier in this
chapter. This will allow our transac-
tion to span each page in the process.
The pages, in order of application
flow, are shown in figure 7.3. As you Figure 7.3 The JSP pages of our
can see, we’ve also created a separate registration
error page we can use to report any
problem with the database or other element of the application.

Step 1: conference.jsp
The responsibilities of the conference selection page (figure 7.4) are to present the
user with a list of conference cities, pulled from the database, and allow him/her to
select any of them which have openings. The source code is shown in listing 7.3.

Listing 7.3 Source code for conference.jsp

<%@ page import="java.sql.*,com.taglib.wdjsp.databases.*" errorPage="error.jsp" %>


<jsp:useBean id="connection" class="ConnectionBean" scope="session"/>
<html>
<body>
<center>
<font size="+2" face="arial"><b>Conference Registration</b></font>
<form action="shuttle.jsp" method="post">
<table border=1 bgcolor="tan" width="50%" align="center">
<tr><td>
<table border="0" bgcolor="white" cellspacing=0 width="100%">
<tr bgcolor="tan">
<th>&nbsp;</th><th>City</th><th>Tickets Remaining</th></tr>
<%
String sql = "SELECT * FROM CONFERENCES";
200 CHAPTER 7
Working with databases

Figure 7.4 The conference selection page

ResultSet results = connection.executeQuery(sql);


while (results.next()) {
if (results.getInt("seats") > 0) {
%>
<td>
<input type="radio" name="show"
value="<%= results.getString("id") %>">
</td>
<% } else { %>
<td>&nbsp;</td>
<% } %>
<td><%= results.getString("city") %></td>
<td align="center"><%= results.getString("seats") %></td>
</tr>
<% } %>
</table>
</td></tr></table>
<p>
<input type="submit" value="Next (Choose Shuttle)">
</form>
</center>
</body>
</html>
Example: JSP conference booking tool 201

Figure 7.5 The shuttle selection page

This is the entry point into our application, but because our simple Connection-
Bean shields the database information from the page, we needn’t do anything spe-
cial to configure it. In fact, each page in our application starts with a block of code
to import our database classes and reference the ConnectionBean from the session,
or—in this case—create a ConnectionBean and place it into the session.
Once we have a connection to the database we can simply build our form using
data from the CONFERENCE table by executing the appropriate query and looping
through it with a while loop. For each row in the table, we verify that there are
seats available before adding a radio button for this city, ensuring that we don’t
allow the user to pick a conference that is full. We use the ID of each conference as
the value of the radio button, to which we have given the name show. We’ll use that
in the next page to hold their seat at the conference. The rest of the code is pretty
straightforward HTML. Clicking the Next button directs the user to the next page
of the application, shuttle.jsp (figure 7.5).

Step 2: shuttle.jsp
The shuttle selection page has a double duty. First it has to act on the information
gathered on the conference selection page. We have to reserve the user a seat at the
selected conference. Secondly, we have to allow the user to pick a conference shuttle
202 CHAPTER 7
Working with databases

selection based on which conference city he/she will be visiting. The source appears
in listing 7.4.

Listing 7.4 Source code for shuttle.jsp

<%@ page import="java.sql.*,com.taglib.wdjsp.databases.*"


errorPage="error.jsp" %>
<jsp:useBean id="connection" class="ConnectionBean"
scope="session"/>

<%
String showID = request.getParameter("show");
connection.setAutoCommit(false);
String sql;
sql = "UPDATE conferences set seats=seats-1 where id=" + showID;
connection.executeUpdate(sql);
%>

<html>
<body>
<center>
<font size="+2" face="arial"><b>Shuttle Reservation</b></font>
<form action="confirm.jsp" method="post">
<table border=1 bgcolor="tan" width="50%" align="center">
<tr><td>
<table border="0" bgcolor="white" cellspacing=0 width="100%">
<tr bgcolor="tan"><th>&nbsp;</th>
<th>Airport</th><th>Time</th><th>Seats Available</th></tr>
<%
sql = "SELECT s.* from shuttles s, conferences c where c.id=" +
showID + " and s.airport = c.airport";
ResultSet results = connection.executeQuery(sql);
while (results.next()) {
if (results.getInt("seats") > 0) {
%>
<td>
<input type="radio" name="shuttle"
value="<%= results.getString("id") %>">
</td>
<% } else { %>
<td>&nbsp;</td>
<% } %>
<td><%= results.getString("airport") %></td>
<td><%= results.getTime("time") %></td>
<td align="center"><%= results.getString("seats") %></td>
</tr>
<% } %>
</table>
</td></tr></table>
Example: JSP conference booking tool 203

<p>
<input type="hidden" name="show" value="<%= showID %>">
<input type="submit" value="Next (Review Reservations)">
</form>
</center>

</body>
</html>

Now, after grabbing a reference to the ConnectionBean from the session, we grab
the selected show ID from the request and stash it in a local variable. We’ll need it
to update the database, plus we’ll pass it on to the pages that follow so we can sum-
marize the user’s selections on the last page.
String showID = request.getParameter("show");

We now actually reserve the user a seat at his or her selected conference, by reduc-
ing the open seat count by one. Before we do this however, we turn off the auto-
commit feature of the database, thereby starting a transaction.
Generating our input form is no different than on the first page of the applica-
tion, though the database query is more complicated.
"SELECT s.* from shuttles s, conferences c WHERE c.id=" +
showID + " and s.airport = c.airport"

That translates into a statement something like this:


SELECT s.* from shuttles s, conferences c
WHERE c.id=12 and s.airport = c.airport

Which, in English, means “perform a join on the tables shuttles and confer-
ences, keeping only the shuttle table’s columns, and select only those rows where
the conference ID is 12 and the conference and shuttle are associated with the same
airport.” This gives us a subset of the available shuttles, showing only those avail-
able for our selected city. (Note that we can specify a table alias after each table’s
name (the s and c values) which keeps us from having to spell out the full table
name each time we use it in the application.)
We then loop through the result set as before, again not allowing the user to
select an entry that is already full. We’ll still need the showID selected in the original
page later in the application, so we’ll carry that on through a hidden form field.
<INPUT TYPE="HIDDEN" NAME="show" VALUE="<%= showID %>">

We could have placed it into the session, but this is just as easy for now and
involves fewer steps. Figure 7.6 shows how the user confirms his/her reservation.
204 CHAPTER 7
Working with databases

Figure 7.6 The confirmation request page

Step 3: confirm.jsp
On this page we must reserve the user’s seat on the selected shuttle, display a sum-
mary of his/her selections from the first two screens, and then ask the user to either
commit or cancel the reservation. Here in listing 7.5 is source code for the page:

Listing 7.5 Source code for confirm.jsp

<%@ page import="java.sql.*,com.taglib.wdjsp.databases.*" errorPage="error.jsp" %>


<jsp:useBean id="connection" class="ConnectionBean" scope="session"/>
<%
String sql;
String shuttleID = request.getParameter("shuttle");
String showID = request.getParameter("show");
sql = "UPDATE shuttles set seats=seats-1 where id=" + shuttleID;
connection.executeUpdate(sql);
sql = "SELECT c.city, c.airport, s.time from conferences c, " +
"shuttles s where c.id=" + showID + " and s.id=" + shuttleID;
ResultSet results = connection.executeQuery(sql);
results.next();
%>
<html>
<body>
<center>
Example: JSP conference booking tool 205

<font size="+2" face="arial"><B>Reservation Confirmation</b></font>


<form action="finish.jsp" method=post>
<table border=1 bgcolor="tan" width="50%" align="center">
<tr><td>
<table border="0" bgcolor="white" cellspacing=0 width="100%">
<tr bgcolor="tan"><th>Summary</th></tr>
<tr><td>
Reservations have been requested for
the <b><%= results.getString("city") %></b>
show, with a complimentary shuttle from
the <b><%= results.getString("airport") %></b> airport
departing at <b><%= results.getTime("time") %></b>.
<p>
To confirm your reservations select commit below.
</td></tr>
</table>
</td></tr></table>

<p>
<input type="submit" name="commit" value="Commit Reservation">
<input type="submit" name="rollback" value="Cancel Reservations">
</body>
</html>

Again, there’s not much new here. We decrement the appropriate shuttle seat
count, just as we did earlier with the conference. We’ve now made all the changes
we plan to make to the database, but remember we are still under transaction con-
trol since we turned off autocommit earlier. We have to disable autocommit only
once, because it is a property of our connection, which we have stored in our ses-
sion via the ConnectionBean.
sql = "UPDATE shuttles set seats = seats - 1 where id = " + shuttleID;
connection.executeUpdate(sql);

The query to get the summary information is a little complicated; we could have
broken it into a couple of separate queries, extracting the appropriate data from
each. However, it’s not necessary.
sql = "SELECT c.city, c.airport, s.time from conferences c, shuttles s where
c.id=" + showID + " and s.id=" + shuttleID;

This selects the columns we are interested in from the intersection of the CONFER-
ENCE and SHUTTLES table where the corresponding ID values match the two selec-
tions the user already made. At that point, we are ready to move on to the final page
(figure 7.7), which, depending on which button the user clicks, will commit the
transaction or roll it back.
206 CHAPTER 7
Working with databases

Figure 7.7 The final page

Step 4: finish.jsp
Listing 7.6 is the final segment of our application.

Listing 7.6 Source code for finish.jsp

<%@ page import="java.sql.*,com.taglib.wdjsp.databases.*"


errorPage="error.jsp" %>
<html>
<body>
<%
ConnectionBean connection =
(ConnectionBean)session.getValue("connection");
if (request.getParameter("commit") != null)
connection.commit();
else
connection.rollback();
session.removeAttribute("connection");
%>
<center>
<% if (request.getParameter("commit") != null) { %>
<font size="+2" face="arial"><b>Reservations Confirmed</b></font>
<p>
Your Reservations confirmed, thanks...
Example: JSP conference booking tool 207

<% } else { %>


<font size="+2" face="arial"><b>Reservations Canceled</b></font>
<p>
Your reservations have been canceled.
<% } %>

<p>
<a href="conference.jsp">Book Another Reservation</a>

</body>
</html>

If the user selected the Commit button, it will show up as a request parameter. If we
detect this we’ll commit the transaction. Otherwise, we’ll call rollback:
if (request.getParameter("commit") != null)
connection.commit();
else
connection.rollback();

After saving our changes, we must get rid of that ConnectionBean to free its
resources, including the database we’ve been holding. So, we simply remove the
connection object from the session.
session.removeAttribute("connection");

The last step is to give the user feedback, with an if block, based on his/her deci-
sion. All in all the flow through this example is straightforward and linear. To wrap
this example up, let’s look at the error page.

The error.jsp page


This page (see listing 7.7) is referenced as an error handler for each page in the
application. If any exception occurs in the course of communicating with the data-
base, it will be forwarded to this page.

Listing 7.7 Source code for error.jsp

<%@ page import="java.sql.*,com.taglib.wdjsp.databases.*"


isErrorPage="true" %>
<html>
<body>
<%
if (exception instanceof SQLException) {
try {
ConnectionBean connection = (ConnectionBean)session.getAttribute("connection");
connection.getConnection().rollback();
208 CHAPTER 7
Working with databases

session.removeAttribute("connection");
}
catch (SQLException e) { }
}
%>
<center>
<font size="+2" face="arial"><b>Application Error</b></font>
<p>
An error has occurred: <tt><%= exception %></tt>
<p>
<a href="conference.jsp">Book Another Reservation</a>
</center>
</body>
</html>

On this page we try to clean up some things and let the user know what has hap-
pened. In the code we abort our transactions and remove the connection object
from our session when an error occurs. We’ll see more detailed discussion on creat-
ing error pages in chapter 11.

Das könnte Ihnen auch gefallen