Tải bản đầy đủ (.pdf) (187 trang)

Advanced Java 2 Platform HOW TO PROGRAM phần 4 potx

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (2.05 MB, 187 trang )

Chapter 8 Java Database Connectivity (JDBC) 499
database and uses that information to set the parameters of PreparedStatements
sqlUpdateName (lines 208–210), sqlUpdateAddress (lines 220–225), sqlUp-
datePhone (lines 235–236) and sqlUpdateEmail (lines 246–247). Note that param-
eter values are set by invoking PreparedStatement set methods for the appropriate
data type. In this example, the ID parameters are all integers and the remaining data are all
strings, so the program uses methods setInt and setString to specify parameters.
After setting the parameters for a particular PreparedStatement, the method calls that
statement’s executeUpdate method (lines 211, 226, 237 and 248), which returns an
integer indicating the number of rows modified by the update. The execution of each Pre-
paredStatement is followed by an if structure that tests the return value of exe-
cuteUpdate. If executeUpdate returns 0, the PreparedStatement did not
update any records. Therefore, savePerson invokes Connection method rollback
to restore the database to its state before the PreparedStatement executed and returns
false to indicate to the AddressBook application that the update failed. If save-
Person reaches line 256, it commits the transaction in the database and returns true to
indicate that the update was successful.
CloudscapeDataAccess method newPerson (lines 278–367) is similar to
method savePerson. Method newPerson receives an AddressBookEntry con-
taining the complete information for a person to insert in the database and uses that infor-
mation to set the parameters of PreparedStatements sqlInsertName (lines 286–
287), sqlInsertAddress (lines 303–313), sqlInsertPhone (lines 323–325) and
sqlInsertEmail (lines 335–337). The primary difference between newPerson and
savePerson is that the entry does not exist in the database yet. To insert rows in tables
addresses, phoneNumbers and emailAddresses, the personID foreign-key
field for each new record must correspond to the personID primary-key field in the
names table. The new personID in table names is not known until the program inserts
the new record in the table. So, after inserting a new record into table names, line 297 exe-
cutes PreparedStatement sqlPersonID to obtain the personID number for the
last new person added to table names. Line 300 places this value in the local variable
personID. Then, the program inserts records in tables addresses, phoneNumbers


and emailAddresses, using the new personID as the value of the foreign-key field
in each table. As in method savePerson, if no records are inserted after a given Pre-
paredStatement executes, method newPerson rolls back the transaction and returns
false to indicate that the insertion failed. Otherwise, method newPerson commits the
transaction and returns true to indicate that the insertion succeeded.
CloudscapeDataAccess method deletePerson (lines 371–435) receives an
AddressBookEntry containing the personID of the person to remove from the data-
base and uses that ID as the parameter value for the PreparedStatements
sqlDeleteName, sqlDeleteAddress, sqlDeletePhone and sqlDelete-
Email. When each PreparedStatement executes, it deletes all records with the spec-
ified personID in the appropriate table. If any part of the delete fails, method
deletePerson rolls back the transaction and returns false to indicate that the deletion
failed. Otherwise, method deletePerson commits the transaction and returns true to
indicate that the deletion succeeded. In the future, if this program supports multiple
addresses, phone numbers and e-mail addresses for each person, this deletePerson
method will delete all the information for a particular entry properly.
500 Java Database Connectivity (JDBC) Chapter 8
CloudscapeDataAccess methods close (lines 438–463) and finalize
(lines 467–470) close the PreparedStatements and database connection. Method
finalize is provided in case an object of class CloudscapeDataAccess gets gar-
bage collected and the client forgot to call close explicitly.
Class AddressBookEntryFrame (Fig. 8.37) is a subclass of JInternalFrame
that enables address-book application users to view or edit the details of an Address-
BookEntry. The AddressBook application class (Fig. 8.38) creates a new Address-
BookEntryFrame to display the results of a search for an entry and to enable the user to
input information for a new entry. AddressBookEntryFrame maintains a reference to
the currently displayed AddressBookEntry and provides set and get methods to
specify an AddressBookEntry to display and to return the currently displayed
AddressBookEntry, respectively. The class also has several private utility methods
for setting up the GUI and accessing the individual JTextFields in the GUI. Objects of

class AddressBookEntryFrame are managed by class AddressBook, which con-
tains a JDesktopPane.
1 // Fig. 8.37: AddressBookEntryFrame.java
2 // A subclass of JInternalFrame customized to display and
3 // an AddressBookEntry or set an AddressBookEntry's properties
4 // based on the current data in the UI.
5 package com.deitel.advjhtp1.jdbc.addressbook;
6
7 // Java core packages
8 import java.util.*;
9 import java.awt.*;
10
11 // Java extension packages
12 import javax.swing.*;
13
14 public class AddressBookEntryFrame extends JInternalFrame {
15
16 // HashMap to store JTextField references for quick access
17 private HashMap fields;
18
19 // current AddressBookEntry set by AddressBook application
20 private AddressBookEntry person;
21
22 // panels to organize GUI
23 private JPanel leftPanel, rightPanel;
24
25 // static integers used to determine new window positions
26 // for cascading windows
27 private static int xOffset = 0, yOffset = 0;
28

29 // static Strings that represent name of each text field.
30 // These are placed on JLabels and used as keys in
31 // HashMap fields.
32 private static final String FIRST_NAME = "First Name",
Fig. 8.37
Fig. 8.37Fig. 8.37
Fig. 8.37
AddressBookEntryFrame for viewing and editing an
AddressBookEntry (part 1 of 3).
Chapter 8 Java Database Connectivity (JDBC) 501
33 LAST_NAME = "Last Name", ADDRESS1 = "Address 1",
34 ADDRESS2 = "Address 2", CITY = "City", STATE = "State",
35 ZIPCODE = "Zipcode", PHONE = "Phone", EMAIL = "Email";
36
37 // construct GUI
38 public AddressBookEntryFrame()
39 {
40 super( "Address Book Entry", true, true );
41
42 fields = new HashMap();
43
44 leftPanel = new JPanel();
45 leftPanel.setLayout( new GridLayout( 9, 1, 0, 5 ) );
46 rightPanel = new JPanel();
47 rightPanel.setLayout( new GridLayout( 9, 1, 0, 5 ) );
48
49 createRow( FIRST_NAME );
50 createRow( LAST_NAME );
51 createRow( ADDRESS1 );
52 createRow( ADDRESS2 );

53 createRow( CITY );
54 createRow( STATE );
55 createRow( ZIPCODE );
56 createRow( PHONE );
57 createRow( EMAIL );
58
59 Container container = getContentPane();
60 container.add( leftPanel, BorderLayout.WEST );
61 container.add( rightPanel, BorderLayout.CENTER );
62
63 setBounds( xOffset, yOffset, 300, 300 );
64 xOffset = ( xOffset + 30 ) % 300;
65 yOffset = ( yOffset + 30 ) % 300;
66 }
67
68 // set AddressBookEntry then use its properties to
69 // place data in each JTextField
70 public void setAddressBookEntry( AddressBookEntry entry )
71 {
72 person = entry;
73
74 setField( FIRST_NAME, person.getFirstName() );
75 setField( LAST_NAME, person.getLastName() );
76 setField( ADDRESS1, person.getAddress1() );
77 setField( ADDRESS2, person.getAddress2() );
78 setField( CITY, person.getCity() );
79 setField( STATE, person.getState() );
80 setField( ZIPCODE, person.getZipcode() );
81 setField( PHONE, person.getPhoneNumber() );
82 setField( EMAIL, person.getEmailAddress() );

83 }
84
Fig. 8.37
Fig. 8.37Fig. 8.37
Fig. 8.37
AddressBookEntryFrame for viewing and editing an
AddressBookEntry (part 2 of 3).
502 Java Database Connectivity (JDBC) Chapter 8
85 // store AddressBookEntry data from GUI and return
86 // AddressBookEntry
87 public AddressBookEntry getAddressBookEntry()
88 {
89 person.setFirstName( getField( FIRST_NAME ) );
90 person.setLastName( getField( LAST_NAME ) );
91 person.setAddress1( getField( ADDRESS1 ) );
92 person.setAddress2( getField( ADDRESS2 ) );
93 person.setCity( getField( CITY ) );
94 person.setState( getField( STATE ) );
95 person.setZipcode( getField( ZIPCODE ) );
96 person.setPhoneNumber( getField( PHONE ) );
97 person.setEmailAddress( getField( EMAIL ) );
98
99 return person;
100 }
101
102 // set text in JTextField by specifying field's
103 // name and value
104 private void setField( String fieldName, String value )
105 {
106 JTextField field =

107 ( JTextField ) fields.get( fieldName );
108
109 field.setText( value );
110 }
111
112 // get text in JTextField by specifying field's name
113 private String getField( String fieldName )
114 {
115 JTextField field =
116 ( JTextField ) fields.get( fieldName );
117
118 return field.getText();
119 }
120
121 // utility method used by constructor to create one row in
122 // GUI containing JLabel and JTextField
123 private void createRow( String name )
124 {
125 JLabel label = new JLabel( name, SwingConstants.RIGHT );
126 label.setBorder(
127 BorderFactory.createEmptyBorder( 5, 5, 5, 5 ) );
128 leftPanel.add( label );
129
130 JTextField field = new JTextField( 30 );
131 rightPanel.add( field );
132
133 fields.put( name, field );
134 }
135 } // end class AddressBookEntryFrame
Fig. 8.37

Fig. 8.37Fig. 8.37
Fig. 8.37
AddressBookEntryFrame for viewing and editing an
AddressBookEntry (part 3 of 3).
Chapter 8 Java Database Connectivity (JDBC) 503
Class AddressBook (Fig. 8.38) is the main application class for the address-book
application. AddressBook uses several of the GUI techniques presented in Chapter 2,
including tool bars, menus, actions and multiple-document interfaces. The discussion of
class AddressBook concentrates on the functionality, rather than on the GUI details.
Screen captures demonstrating the program’s execution appear in Fig. 8.39.
1 // Fig. 8.38: AddressBook.java
2 // An address book database example that allows information to
3 // be inserted, updated and deleted. The example uses
4 // transactions to ensure that the operations complete
5 // successfully.
6 package com.deitel.advjhtp1.jdbc.addressbook;
7
8 // Java core packages
9 import java.awt.*;
10 import java.awt.event.*;
11 import java.sql.*;
12
13 // Java extension packages
14 import javax.swing.*;
15 import javax.swing.event.*;
16
17 public class AddressBook extends JFrame {
18
19 // reference for manipulating multiple document interface
20 private JDesktopPane desktop;

21
22 // reference to database access object
23 private AddressBookDataAccess database;
24
25 // references to Actions
26 Action newAction, saveAction, deleteAction,
27 searchAction, exitAction;
28
29 // set up database connection and GUI
30 public AddressBook()
31 {
32 super( "Address Book" );
33
34 // create database connection
35 try {
36 database = new CloudscapeDataAccess();
37 }
38
39 // detect problems with database connection
40 catch ( Exception exception ) {
41 exception.printStackTrace();
42 System.exit( 1 );
43 }
44
Fig. 8.38
Fig. 8.38Fig. 8.38
Fig. 8.38
AddressBook application class that enables the user to interact with the
addressbook database (part 1 of 8).
504 Java Database Connectivity (JDBC) Chapter 8

45 // database connection successful, create GUI
46 JToolBar toolBar = new JToolBar();
47 JMenu fileMenu = new JMenu( "File" );
48 fileMenu.setMnemonic( 'F' );
49
50 // Set up actions for common operations. Private inner
51 // classes encapsulate the processing of each action.
52 newAction = new NewAction();
53 saveAction = new SaveAction();
54 saveAction.setEnabled( false ); // disabled by default
55 deleteAction = new DeleteAction();
56 deleteAction.setEnabled( false ); // disabled by default
57 searchAction = new SearchAction();
58 exitAction = new ExitAction();
59
60 // add actions to tool bar
61 toolBar.add( newAction );
62 toolBar.add( saveAction );
63 toolBar.add( deleteAction );
64 toolBar.add( new JToolBar.Separator() );
65 toolBar.add( searchAction );
66
67 // add actions to File menu
68 fileMenu.add( newAction );
69 fileMenu.add( saveAction );
70 fileMenu.add( deleteAction );
71 fileMenu.addSeparator();
72 fileMenu.add( searchAction );
73 fileMenu.addSeparator();
74 fileMenu.add( exitAction );

75
76 // set up menu bar
77 JMenuBar menuBar = new JMenuBar();
78 menuBar.add( fileMenu );
79 setJMenuBar( menuBar );
80
81 // set up desktop
82 desktop = new JDesktopPane();
83
84 // get the content pane to set up GUI
85 Container c = getContentPane();
86 c.add( toolBar, BorderLayout.NORTH );
87 c.add( desktop, BorderLayout.CENTER );
88
89 // register for windowClosing event in case user
90 // does not select Exit from File menu to terminate
91 // application
92 addWindowListener(
93 new WindowAdapter() {
94 public void windowClosing( WindowEvent event )
95 {
96 shutDown();
Fig. 8.38
Fig. 8.38Fig. 8.38
Fig. 8.38
AddressBook application class that enables the user to interact with the
addressbook database (part 2 of 8).
Chapter 8 Java Database Connectivity (JDBC) 505
97 }
98 }

99 );
100
101 // set window size and display window
102 Toolkit toolkit = getToolkit();
103 Dimension dimension = toolkit.getScreenSize();
104
105 // center window on screen
106 setBounds( 100, 100, dimension.width - 200,
107 dimension.height - 200 );
108
109 setVisible( true );
110 } // end AddressBook constructor
111
112 // close database connection and terminate program
113 private void shutDown()
114 {
115 database.close(); // close database connection
116 System.exit( 0 ); // terminate program
117 }
118
119 // create a new AddressBookEntryFrame and register listener
120 private AddressBookEntryFrame createAddressBookEntryFrame()
121 {
122 AddressBookEntryFrame frame = new AddressBookEntryFrame();
123 setDefaultCloseOperation( DISPOSE_ON_CLOSE );
124 frame.addInternalFrameListener(
125 new InternalFrameAdapter() {
126
127 // internal frame becomes active frame on desktop
128 public void internalFrameActivated(

129 InternalFrameEvent event )
130 {
131 saveAction.setEnabled( true );
132 deleteAction.setEnabled( true );
133 }
134
135 // internal frame becomes inactive frame on desktop
136 public void internalFrameDeactivated(
137 InternalFrameEvent event )
138 {
139 saveAction.setEnabled( false );
140 deleteAction.setEnabled( false );
141 }
142 } // end InternalFrameAdapter anonymous inner class
143 ); // end call to addInternalFrameListener
144
145 return frame;
146 } // end method createAddressBookEntryFrame
147
Fig. 8.38
Fig. 8.38Fig. 8.38
Fig. 8.38
AddressBook application class that enables the user to interact with the
addressbook database (part 3 of 8).
506 Java Database Connectivity (JDBC) Chapter 8
148 // method to launch program execution
149 public static void main( String args[] )
150 {
151 new AddressBook();
152 }

153
154 // Private inner class defines action that enables
155 // user to input new entry. User must "Save" entry
156 // after inputting data.
157 private class NewAction extends AbstractAction {
158
159 // set up action's name, icon, descriptions and mnemonic
160 public NewAction()
161 {
162 putValue( NAME, "New" );
163 putValue( SMALL_ICON, new ImageIcon(
164 getClass().getResource( "images/New24.png" ) ) );
165 putValue( SHORT_DESCRIPTION, "New" );
166 putValue( LONG_DESCRIPTION,
167 "Add a new address book entry" );
168 putValue( MNEMONIC_KEY, new Integer( 'N' ) );
169 }
170
171 // display window in which user can input entry
172 public void actionPerformed( ActionEvent e )
173 {
174 // create new internal window
175 AddressBookEntryFrame entryFrame =
176 createAddressBookEntryFrame();
177
178 // set new AddressBookEntry in window
179 entryFrame.setAddressBookEntry(
180 new AddressBookEntry() );
181
182 // display window

183 desktop.add( entryFrame );
184 entryFrame.setVisible( true );
185 }
186
187 } // end inner class NewAction
188
189 // inner class defines an action that can save new or
190 // updated entry
191 private class SaveAction extends AbstractAction {
192
193 // set up action's name, icon, descriptions and mnemonic
194 public SaveAction()
195 {
196 putValue( NAME, "Save" );
197 putValue( SMALL_ICON, new ImageIcon(
198 getClass().getResource( "images/Save24.png" ) ) );
199 putValue( SHORT_DESCRIPTION, "Save" );
Fig. 8.38
Fig. 8.38Fig. 8.38
Fig. 8.38
AddressBook application class that enables the user to interact with the
addressbook database (part 4 of 8).
Chapter 8 Java Database Connectivity (JDBC) 507
200 putValue( LONG_DESCRIPTION,
201 "Save an address book entry" );
202 putValue( MNEMONIC_KEY, new Integer( 'S' ) );
203 }
204
205 // save new entry or update existing entry
206 public void actionPerformed( ActionEvent e )

207 {
208 // get currently active window
209 AddressBookEntryFrame currentFrame =
210 ( AddressBookEntryFrame ) desktop.getSelectedFrame();
211
212 // obtain AddressBookEntry from window
213 AddressBookEntry person =
214 currentFrame.getAddressBookEntry();
215
216 // insert person in address book
217 try {
218
219 // Get personID. If 0, this is a new entry;
220 // otherwise an update must be performed.
221 int personID = person.getPersonID();
222
223 // determine string for message dialogs
224 String operation =
225 ( personID == 0 ) ? "Insertion" : "Update";
226
227 // insert or update entry
228 if ( personID == 0 )
229 database.newPerson( person );
230 else
231 database.savePerson( person );
232
233 // display success or failure message
234 JOptionPane.showMessageDialog( desktop,
235 operation + " successful" );
236 } // end try

237
238 // detect database errors
239 catch ( DataAccessException exception ) {
240 JOptionPane.showMessageDialog( desktop, exception,
241 "DataAccessException",
242 JOptionPane.ERROR_MESSAGE );
243 exception.printStackTrace();
244 }
245
246 // close current window and dispose of resources
247 currentFrame.dispose();
248
249 } // end method actionPerformed
250
251 } // end inner class SaveAction
Fig. 8.38
Fig. 8.38Fig. 8.38
Fig. 8.38
AddressBook application class that enables the user to interact with the
addressbook database (part 5 of 8).
508 Java Database Connectivity (JDBC) Chapter 8
252
253 // inner class defines action that deletes entry
254 private class DeleteAction extends AbstractAction {
255
256 // set up action's name, icon, descriptions and mnemonic
257 public DeleteAction()
258 {
259 putValue( NAME, "Delete" );
260 putValue( SMALL_ICON, new ImageIcon(

261 getClass().getResource( "images/Delete24.png" ) ) );
262 putValue( SHORT_DESCRIPTION, "Delete" );
263 putValue( LONG_DESCRIPTION,
264 "Delete an address book entry" );
265 putValue( MNEMONIC_KEY, new Integer( 'D' ) );
266 }
267
268 // delete entry
269 public void actionPerformed( ActionEvent e )
270 {
271 // get currently active window
272 AddressBookEntryFrame currentFrame =
273 ( AddressBookEntryFrame ) desktop.getSelectedFrame();
274
275 // get AddressBookEntry from window
276 AddressBookEntry person =
277 currentFrame.getAddressBookEntry();
278
279 // If personID is 0, this is new entry that has not
280 // been inserted. Therefore, delete is not necessary.
281 // Display message and return.
282 if ( person.getPersonID() == 0 ) {
283 JOptionPane.showMessageDialog( desktop,
284 "New entries must be saved before they can be " +
285 "deleted. \nTo cancel a new entry, simply " +
286 "close the window containing the entry" );
287 return;
288 }
289
290 // delete person

291 try {
292 database.deletePerson( person );
293
294 // display message indicating success
295 JOptionPane.showMessageDialog( desktop,
296 "Deletion successful" );
297 }
298
299 // detect problems deleting person
300 catch ( DataAccessException exception ) {
301 JOptionPane.showMessageDialog( desktop, exception,
302 "Deletion failed", JOptionPane.ERROR_MESSAGE );
Fig. 8.38
Fig. 8.38Fig. 8.38
Fig. 8.38
AddressBook application class that enables the user to interact with the
addressbook database (part 6 of 8).
Chapter 8 Java Database Connectivity (JDBC) 509
303 exception.printStackTrace();
304 }
305
306 // close current window and dispose of resources
307 currentFrame.dispose();
308
309 } // end method actionPerformed
310
311 } // end inner class DeleteAction
312
313 // inner class defines action that locates entry
314 private class SearchAction extends AbstractAction {

315
316 // set up action's name, icon, descriptions and mnemonic
317 public SearchAction()
318 {
319 putValue( NAME, "Search" );
320 putValue( SMALL_ICON, new ImageIcon(
321 getClass().getResource( "images/Find24.png" ) ) );
322 putValue( SHORT_DESCRIPTION, "Search" );
323 putValue( LONG_DESCRIPTION,
324 "Search for an address book entry" );
325 putValue( MNEMONIC_KEY, new Integer( 'r' ) );
326 }
327
328 // locate existing entry
329 public void actionPerformed( ActionEvent e )
330 {
331 String lastName =
332 JOptionPane.showInputDialog( desktop,
333 "Enter last name" );
334
335 // if last name was input, search for it; otherwise,
336 // do nothing
337 if ( lastName != null ) {
338
339 // Execute search. If found, AddressBookEntry
340 // is returned containing data.
341 AddressBookEntry person = database.findPerson(
342 lastName );
343
344 if ( person != null ) {

345
346 // create window to display AddressBookEntry
347 AddressBookEntryFrame entryFrame =
348 createAddressBookEntryFrame();
349
350 // set AddressBookEntry to display
351 entryFrame.setAddressBookEntry( person );
352
353 // display window
354 desktop.add( entryFrame );
Fig. 8.38
Fig. 8.38Fig. 8.38
Fig. 8.38
AddressBook application class that enables the user to interact with the
addressbook database (part 7 of 8).
510 Java Database Connectivity (JDBC) Chapter 8
Class AddressBook’s constructor (lines 30–110) creates a Cloudscape-
DataAccess object to interact with the database (line 36), builds the GUI (lines 46–87),
registers an event handler for the window-closing event (lines 92–99) and displays the
application window (lines 102–109). As part of building the tool bar and menu for the
application, lines 52–58 of the constructor create instances of five private inner classes
that implement the actions for the GUI—NewAction (lines 157–187), SaveAction
(lines 191–251), DeleteAction (lines 254–311), SearchAction (lines 314–366) and
ExitAction (lines 370–387). Note that the program disables the SaveAction and
DeleteAction by default. These are enabled only if there is an active internal frame on
the desktop.
Each action (except ExitAction) uses a standard icon from the Sun Microsystems
Java Look and Feel Graphics Repository, located at developer.java.sun.com/
developer/techDocs/hi/repository. The first screen capture of Fig. 8.39
describes each of the icons in the GUI.

355 entryFrame.setVisible( true );
356 }
357 else
358 JOptionPane.showMessageDialog( desktop,
359 "Entry with last name \"" + lastName +
360 "\" not found in address book" );
361
362 } // end "if ( lastName == null )"
363
364 } // end method actionPerformed
365
366 } // end inner class SearchAction
367
368 // inner class defines action that closes connection to
369 // database and terminates program
370 private class ExitAction extends AbstractAction {
371
372 // set up action's name, descriptions and mnemonic
373 public ExitAction()
374 {
375 putValue( NAME, "Exit" );
376 putValue( SHORT_DESCRIPTION, "Exit" );
377 putValue( LONG_DESCRIPTION, "Terminate the program" );
378 putValue( MNEMONIC_KEY, new Integer( 'x' ) );
379 }
380
381 // terminate program
382 public void actionPerformed( ActionEvent e )
383 {
384 shutDown(); // close database connection and terminate

385 }
386
387 } // end inner class ExitAction
388 }
Fig. 8.38
Fig. 8.38Fig. 8.38
Fig. 8.38
AddressBook application class that enables the user to interact with the
addressbook database (part 8 of 8).
Chapter 8 Java Database Connectivity (JDBC) 511
Fig. 8.39
Fig. 8.39Fig. 8.39
Fig. 8.39 Screen captures of the AddressBook application (part 1 of 3).
New Save Delete Search
512 Java Database Connectivity (JDBC) Chapter 8
Fig. 8.39
Fig. 8.39Fig. 8.39
Fig. 8.39 Screen captures of the AddressBook application (part 2 of 3).
Chapter 8 Java Database Connectivity (JDBC) 513
Fig. 8.39
Fig. 8.39Fig. 8.39
Fig. 8.39 Screen captures of the AddressBook application (part 3 of 3).
514 Java Database Connectivity (JDBC) Chapter 8
NewAction (lines 157–187) does not perform any database manipulations. It simply
displays an AddressBookEntryFrame in which the user inputs the information for a
new address book entry. To perform the actual insert into the database, the user must click
the Save button or select Save from the File menu, which invokes the SaveAction.
Class NewAction’s actionPerformed method (lines 172–185) creates a new
AddressBookEntryFrame (lines 175–176), sets a new AddressBookEntry for the
frame (lines 179–180), attaches the frame to the JDesktopPane (line 183) and displays

the frame (line 184).
SaveAction (lines 191–251) determines whether to save a new entry or update an
existing entry based on the personID for the AddressBookEntry in the currently
active internal frame. Method actionPerformed (lines 206–249) obtains a reference to
the active internal frame (lines 209–210) and gets the AddressBookEntry currently
displayed (lines 213–214). Line 221 gets the personID from the AddressBookEntry.
If the personID is 0, the AddressBookEntry represents a new address book entry,
and line 229 invokes the CloudscapeDataAccess object’s newPerson method to
insert a new record in the database. If the personID is not 0, the AddressBookEntry
represents an existing address book entry to update, and line 231 invokes the Cloud-
scapeDataAccess object’s savePerson method to update the record in the database.
Methods newPerson and savePerson each receive an AddressBookEntry as an
argument. Line 247 disposes of the active internal frame after the save operation completes.
DeleteAction (lines 254–311) uses the AddressBookEntry in the currently
active internal frame to remove an entry from the database. Method actionPerformed
(lines 269–309) obtains a reference to the active internal frame (lines 272–273) and gets the
currently displayed AddressBookEntry (lines 276–277). If the personID in the
AddressBookEntry is 0, the entry has not been stored in the database, so action-
Performed displays a message to the user and terminates (lines 282–288). Line 292
invokes the CloudscapeDataAccess object’s deletePerson method, passing the
AddressBookEntry to delete as an argument. Line 307 disposes of the active internal
frame after the delete operation completes.
SearchAction (lines 314–366) searches for an address book entry based on the last
name of the person input by the user. Method actionPerformed (lines 329–364)
obtains the last name for which to search (lines 331–333). If the last name is not null (i.e.,
the user did not click the Cancel button in the input dialog), lines 341–342 create a new
AddressBookEntry reference and invokes database’s findPerson method to
locate the person in the database. If the person exists, findPerson returns the
AddressBookEntry containing the information for that person. Then, actionPer-
formed creates a new AddressBookEntryFrame (lines 347–348), sets the

AddressBookEntry for the frame (line 351), attaches the frame to the JDesktop-
Pane (line 354) and displays the frame (line 355). Otherwise, actionPerformed dis-
plays a message dialog indicating that the record was not found.
In Fig. 8.39, the first screen capture shows the address-book application after the user
clicks the New button to create a new entry. The second screen capture shows the results
after the user inputs the information for the new entry and clicks the Save button to insert
the data in the database. The third and fourth screen captures demonstrate searching for an
entry in the database. The fifth screen capture demonstrates updating the person’s city
information. The sixth screen capture demonstrates deleting the record for the currently dis-
Chapter 8 Java Database Connectivity (JDBC) 515
played entry. [Note: The screen captures do not show that after completing a Save or
Delete operation, the internal frame that displays the entry is removed from the screen.]
8.8 Stored Procedures
Many database management systems can store individual SQL statements or sets of SQL
statements in a database, so that programs accessing that database can invoke them. Such
SQL statements are called stored procedures. JDBC enables programs to invoke stored
procedures using objects that implement interface CallableStatement. Like Pre-
paredStatements, CallableStatements can receive arguments specified with the
methods inherited from interface PreparedStatement. In addition, Call-
ableStatements can specify output parameters in which a stored procedure can place
return values. Interface CallableStatement includes methods to specify which pa-
rameters in a stored procedure are output parameters. The interface also includes methods
to obtain the values of output parameters returned from a stored procedure.
Portability Tip 8.8
Although the syntax for creating stored procedures differs across database management sys-
tems, interface CallableStatement provides a uniform interface for specifying input
and output parameters for stored procedures and for invoking stored procedures.
8.8
Portability Tip 8.9
According to the Java API documentation for interface CallableStatement, for maxi-

mum portability between database systems, programs should process the update counts or
ResultSets returned from a CallableStatement before obtaining the values of any
output parameters.
8.9
8.9 Batch Processing
A series of database updates (e.g., inserts, updates, deletes) can be performed in a batch up-
date to the database. JDBC Statements, PreparedStatements and Call-
ableStatements provide an addBatch method that enables the program to add SQL
statements to a batch for future execution. Each Statement, PreparedStatement or
CallableStatement object maintains its own list of SQL statements to perform in a
batch update. Figure 8.40 describes the batch-processing methods of interfaces State-
ment and PreparedStatement. (CallableStatements inherit the methods of in-
terface PreparedStatement.)
Method Description
public void addBatch( String sql )
Method of interface Statement that receives a String argument
specifying an SQL statement to add to the Statement’s batch for
future execution. This method should not be used with Prepared-
Statements and CallableStatements.
Fig. 8.40
Fig. 8.40Fig. 8.40
Fig. 8.40 Statement and PreparedStatement methods for batch
updates (part 1 of 2).
516 Java Database Connectivity (JDBC) Chapter 8
Each method in Fig. 8.40 throws a BatchUpdateException (a subclass of
SQLException) if database errors occur while executing any of the SQL statements or
if the particular database management system does not support batch update processing.
Method executeBatch also throws BatchUpdateExceptions if the batch update
contains any SQL statements that return ResultSets.
Common Programming Error 8.14

Batch updates are for use only with SQL statements that do not return ResultSets. Exe-
cuting an SQL statement that returns a ResultSet as part of a batch update causes a
BatchUpdateException.
8.14
After adding statements to a batch update, a program invokes Statement method
executeBatch to execute the SQL statements in the batch. This method performs each
SQL statement and returns an array of int values containing the status of each SQL state-
ment. If the database connection is in autocommit mode, the database commits each state-
ment as it completes execution. Otherwise, the program can determine whether or not to
commit the transaction by inspecting the array of return values and then invoke the Con-
nection’s commit or rollback method as appropriate. Figure 8.41 summarizes the
return values of method executeBatch.
public void addBatch()
Method of interface PreparedStatement that adds the statement
to a batch for future execution. This method should be called after set-
ting the parameters for the PreparedStatement. This version of
addBatch also can be used with CallableStatements.
public void clearBatch()
Method of interface Statement that clears the statement’s batch.
public int[] executeBatch()
Method of interface Statement that executes the statement’s batch.
The method returns an array of int values indicating the status of each
SQL statement in the batch. The order of the values in the array corre-
sponds to the order in which the SQL statements are added to the batch.
Method Description
Fig. 8.40
Fig. 8.40Fig. 8.40
Fig. 8.40 Statement and PreparedStatement methods for batch
updates (part 2 of 2).
Return value Description

a value greater than
or equal to 0
Indicates successful execution of the SQL statements in the batch update.
The value specifies the actual number of rows updated in the database.
-2 Indicates successful execution of the SQL statements in the batch update and
that the affected number of rows is unknown.
Fig. 8.41
Fig. 8.41Fig. 8.41
Fig. 8.41 Return values of method executeBatch (part 1 of 2).
Chapter 8 Java Database Connectivity (JDBC) 517
Software Engineering Observation 8.12
Normally, programs disable autocommit mode for a Connection before executing a batch
update. Otherwise, each SQL statement in the batch update is committed individually, which
prevents programs from deciding whether groups of SQL statements should be committed or
rolled back, based on logic in the program.
8.12
8.10 Processing Multiple ResultSets or Update Counts
Some Statements, PreparedStatements and CallableStatements return
multiple ResultSets or update counts. In such cases, programs should use Statement
method execute to execute the SQL statements. After executing SQL statements, meth-
od execute returns a boolean indicating whether the first result is a ResultSet
(true) or an update count (false). Based on execute’s return value, the program in-
vokes method getResultSet or method getUpdateCount to obtain the first result.
The program can obtain subsequent results by calling method getMoreResults.
Figure 8.42 summarizes the methods for processing multiple results. [Note: Each of the
methods in Fig. 8.42 is defined in interface Statement and inherited into interfaces
PreparedStatement and CallableStatement.]
-3 Indicates an SQL statement that failed to execute properly during a batch
update. When the batch update is allowed to complete its processing, the
array returned by getUpdateCounts contains the value -3 for any SQL

statement that failed. When the batch update is not allowed to continue after
an exception, the array returned by getUpdateCounts contains elements
for only the SQL statements that executed successfully before the exception
occurred. When a failure occurs, executeUpdate throws a Batch-
UpdateException. In such cases, the program can catch the exception
and invoke BatchUpdateException method getUpdateCounts to
obtain the array of update counts. Some databases allow a batch update to
continue executing when an exception occurs, while others do not.
Return value Description
Fig. 8.41
Fig. 8.41Fig. 8.41
Fig. 8.41 Return values of method executeBatch (part 2 of 2).
Method Description
public boolean execute()
Programs use this method to execute SQL statements that can return multiple
ResultSets or update counts. This method returns a boolean indicating
whether the first result is a ResultSet (true) or an update count
(false). Based on the value returned, the program can call getResult-
Set or getUpdateCount to obtain the first result.
Fig. 8.42
Fig. 8.42Fig. 8.42
Fig. 8.42 Statement methods that enable processing of multiple results
returned by method
execute (part 1 of 2).
518 Java Database Connectivity (JDBC) Chapter 8
Software Engineering Observation 8.13
A program has completed processing the results returned by method execute when method
getMoreResults returns false and method getUpdateCount returns -1.
8.13
8.11 Updatable ResultSets

Some JDBC drivers support updatable ResultSets. Such ResultSets enable a pro-
gram to insert, update and delete records using methods of interface ResultSet. If the
JDBC driver supports updatable ResultSets, the program can invoke Connection
method createStatement, prepareStatement or prepareCall and specify
the constant ResultSet.CONCUR_UPDATABLE as the second argument (the first argu-
ment specifies the type of scrolling supported by the ResultSet).
Software Engineering Observation 8.14
Normally, a query that produces an updatable ResultSet must select a table’s primary
key, so that updates can determine the proper records to manipulate in the database. Other-
wise, the query returns a read-only ResultSet.
8.14
Interface ResultSet provides update methods that enable the program to specify
new values for particular columns in the current ResultSet row. In addition, interface
ResultSet provides methods deleteRow, insertRow and updateRow to manipu-
late the ResultSet and the underlying database. Method deleteRow deletes the cur-
rent ResultSet row from the ResultSet and the database. Method updateRow
updates the current row in the ResultSet and the database. Method insertRow inserts
a new row in the ResultSet and the database. Every updatable ResultSet maintains
public boolean getMoreResults()
After obtaining the first result returned from method execute, a program
invokes this method to move to the next result. This method returns a bool-
ean indicating whether the next result is a ResultSet (true) or an
update count (false). Based on the value returned, the program can call
getResultSet or getUpdateCount to obtain the next result.
public ResultSet getResultSet()
Obtains a ResultSet from the results returned by method execute. This
method returns null if the result is not a ResultSet or if there are no
more results.
public int getUpdateCount()
Obtains an update count from the results returned by method execute.

This method returns -1 if the result is not an update count or if there are no
more results.
Method Description
Fig. 8.42
Fig. 8.42Fig. 8.42
Fig. 8.42 Statement methods that enable processing of multiple results
returned by method
execute (part 2 of 2).
Chapter 8 Java Database Connectivity (JDBC) 519
an insert row where the program can build a new record before inserting it in the
ResultSet and the database. Before invoking ResultSet’s update methods to build
the new record, the program must invoke ResultSet method moveToInsertRow.
The ResultSet keeps track of the cursor’s location before that operation. The program
can return to the cursor location to continue processing the ResultSet by invoking
ResultSet method moveToCurrentRow.
8.12 JDBC 2.0 Optional Package javax.sql
In addition to the classes and interfaces of package java.sql, many database vendors
now support the JDBC 2.0 optional package javax.sql. Typically, this package is in-
cluded with the implementation of the Java 2 Enterprise Edition. Some of the key interfaces
in package javax.sql include DataSource, ConnectionPoolDataSource,
PooledConnection and RowSet. Each of these interfaces is explained briefly in the
next several subsections.
8.12.1 DataSource
A DataSource is new way for programs to obtain database connections. Enterprise Java
applications often access information and resources (such as databases) that are external to
those applications. In some cases, resources are distributed across a network. Enterprise ap-
plication components must be able to locate the resources they use. An Enterprise Java ap-
plication container must provide a naming service that implements the Java Naming and
Directory Interface (JNDI) and enables the components executing in that container to per-
form name lookups to locate resources. Typically, DataSources are registered with a

JNDI service that enables a program to locate the DataSource. Chapter 11 demonstrates
our first Enterprise Java application that uses a JNDI service to look up a DataSource
and connect to a database.
8.12.2 Connection Pooling
The process of connecting to a database requires substantial overhead in both time and re-
sources. In a program that performs many separate database connections (such as a server
in a Web-based shopping-cart application), such overhead can become a burden on the pro-
gram. Applications can establish connection pools that maintain many database connec-
tions to eliminate the overhead of connecting to the database while many clients are waiting
for responses in distributed applications. These connection objects can be shared between
the application clients.
Databases that provide full support for the JDBC optional package include implemen-
tations of interfaces ConnectionPoolDataSource and PooledConnection.
Like DataSources ConnectionPoolDataSources typically are registered with a
JNDI service, so that a program can locate them dynamically. After obtaining a reference
to a ConnectionPoolDataSource, a program can invoke its getPooledConnec-
tion method to obtain a PooledConnection object that represents the connection to
the database. PooledConnection method getConnection returns the underlying
Connection object that the program uses to create Statements, PreparedState-
ments and CallableStatements for executing SQL statements.
520 Java Database Connectivity (JDBC) Chapter 8
8.12.3 RowSets
The JDBC optional package introduces a new interface, RowSet, for manipulating tabular
data sources such as ResultSets. RowSets are not implemented as part of the database
driver. Instead, they are implemented as JavaBeans that encapsulate a tabular data source.
Interface RowSet extends interface ResultSet. Thus, a RowSet object has all the
functionality of a ResultSet, including the ability to scroll through the records, insert
new records, update existing records and delete existing records. What makes a RowSet
interesting is that all of these features are supported regardless of whether the ResultSet
implementation provided by a particular database driver supports these features. For

example, a program can create a RowSet based on a ResultSet, disconnect from the
database and allow the program to update the data in the RowSet. Then the RowSet can
connect to the database and update it, based on the changes made to the data in the
RowSet. All of this can be accomplished even if the database driver does not support
updatable ResultSets. RowSets that disconnect from the database and then reconnect
to perform updates are called disconnected RowSets.
Unlike ResultSets, RowSets implementations can be serializable, so they can be
saved locally or transmitted across a network. RowSets also support JavaBean events
(with interface RowSetListener and class RowSetEvent) that enable an application
using a RowSet to be notified when the RowSet cursor moves, a record is inserted, a
record is updated, a record is deleted or the entire set of data in the RowSet changes.
RowSets also allow a program to set parameters to the RowSet’s command string—nor-
mally, the SQL statement that obtains the data.
If you are interested in experimenting with RowSets, Sun Microsystems has three
early access RowSet implementations available at
developer.java.sun.com/developer/earlyAccess/crs
These implementations are CachedRowSet, WebRowSet and JDBCRowSet.
Class CachedRowSet defines a disconnected RowSet that can be serialized.
CachedRowSet provides full support for scrolling through data and updating data—both
particularly useful in applications that require these capabilities even if the database
driver’s ResultSet implementation does not support scrolling through and updating
data. The fact that CachedRowSets are serializable enables them to be sent across a net-
work in a distributed network application.
Class WebRowSet is a subclass of CachedRowSet that enables RowSet data to be
output as an XML document. Class JDBCRowSet defines a connected RowSet that encap-
sulates a ResultSet to make the ResultSet appear like a JavaBean to the program.
For a tutorial on using the Sun Microsystems, Inc., RowSet implementations, visit
developer.java.sun.com/developer/Books/JDBCTutorial/
chapter5.html
Also, check your database management system’s documentation to determine whether your

database provides any RowSet implementations.
8.13 Internet and World Wide Web Resources
java.sun.com/products/jdbc
Sun Microsystems, Inc.’s JDBC home page.
Chapter 8 Java Database Connectivity (JDBC) 521
java.sun.com/docs/books/tutorial/jdbc/index.html
The Sun Microsystems, Inc., Java Tutorial’s JDBC track.
www.sql.org
This SQL portal provides links to many resources, including SQL syntax, tips, tutorials, books, mag-
azines, discussion groups, companies with SQL services, SQL consultants and free software.
industry.java.sun.com/products/jdbc/drivers
Sun Microsystems, Inc., search engine for locating JDBC drivers.
java.sun.com/j2se/1.3/docs/guide/jdbc/index.html
Sun Microsystems, Inc.’s JDBC API documentation.
java.sun.com/products/jdbc/faq.html
Sun Microsystems, Inc.’s frequently asked questions on JDBC.
www.jguru.com/jguru/faq/faqpage.jsp?name=JDBC
The JGuru JDBC FAQs.
www.cloudscape.com
This site is Informix’s Cloudscape database home page. Here, you can download the latest version of
Cloudscape and access all of its documentation on line.
java.sun.com/products/jdbc/articles/package2.html
An overview of the JDBC 2.0 optional package API.
developer.java.sun.com/developer/earlyAccess/crs
Early access to the Sun RowSet implementations. [Note: You may need to register at the Java Devel-
oper Connection (developer.java.sun.com/developer/index.html) before down-
loading from this site.]
developer.java.sun.com/developer/Books/JDBCTutorial/chapter5.html
Chapter 5 (RowSet Tutorial) of the book The JDBC 2.0 API Tutorial and Reference, Second Edition.
SUMMARY

• A database is an integrated collection of data. A database management system (DBMS) provides
mechanisms for storing and organizing data.
• Today’s most popular database systems are relational databases.
• A language called Structured Query Language (SQL) is used almost universally with relational da-
tabase systems to perform queries and manipulate data.
• A programming language connects to, and interacts with, relational databases via an interface—
software that facilitates communications between a database management system and a program.
• Java programmers communicate with databases and manipulate their data using the Java Database
Connectivity (JDBC) API. A JDBC driver implements the interface to a particular database.
• A relational database is composed of tables. A row of a table is called a record (or row).
• A primary key is a field that contains unique data that cannot be duplicated in other records.
• Each column of the table represents a different field (or column or attribute).
• The primary key can be composed of more than one column (or field) in the database.
• SQL provides a complete set of commands that enable programmers to define complex queries
that select data from a table. The results of a query are commonly called result sets (or record sets).
• Every record must have a value in the primary-key field, and that value must be unique. This is
known as the Rule of Entity Integrity.
522 Java Database Connectivity (JDBC) Chapter 8
• A one-to-many relationship between tables indicates that a record in one table can have many
records in a separate table.
• A foreign key is a field for which every entry in one table has a unique value in another table and
where the field in the other table is the primary key for that table.
• The foreign key helps maintain the Rule of Referential Integrity: Every foreign key field value
must appear in another table’s primary key field. Foreign keys enable information from multiple
tables to be joined together for analysis purposes. There is a one-to-many relationship between a
primary key and its corresponding foreign key.
• The simplest format of a SELECT query is
SELECT * FROM tableName
where the asterisk (*) indicates that all rows and columns from tableName should be selected and
tableName specifies the table in the database from which the data will be selected.

• To select specific fields from a table, replace the asterisk (*) with a comma-separated list of the
field names to select.
• Programmers process result sets by knowing in advance the order of the fields in the result set.
Specifying the field names to select guarantees that the fields are always returned in the specified
order, even if the actual order of the fields in the database table(s) changes.
• The optional WHERE clause in a SELECT query specifies the selection criteria for the query. The
simplest format of a SELECT query with selection criteria is
SELECT fieldName1, fieldName2, … FROM tableName WHERE criteria
•The WHERE clause condition can contain operators <, >, <=, >=, =, <> and LIKE. Operator LIKE
is used for pattern matching with wildcard characters percent (%) and underscore (_).
• A percent character (%) in a pattern indicates that a string matching the pattern can have zero or
more characters at the percent character’s location in the pattern.
• An underscore ( _ ) in the pattern string indicates a single character at that position in the pattern.
• The results of a query can be arranged in ascending or descending order using the optional ORDER
BY clause. The simplest form of an ORDER BY clause is
SELECT fieldName1, fieldName2, … FROM tableName ORDER BY field ASC
SELECT fieldName1, fieldName2, … FROM tableName ORDER BY field DESC
where ASC specifies ascending order, DESC specifies descending order and field specifies the field
on which the sort is based. The default sorting order is ascending, so ASC is optional.
• Multiple fields can be used for ordering purposes with an ORDER BY clause of the form
ORDER BY field1 sortingOrder, field2 sortingOrder, …
•The WHERE and ORDER BY clauses can be combined in one query.
• A join merges records from two or more tables by testing for matching values in a field that is com-
mon to both tables. The simplest format of a join is
SELECT fieldName1, fieldName2, …
FROM table1, table2
WHERE table1.fieldName = table2.fieldName
The query’s WHERE clause specifies the fields from each table that should be compared to deter-
mine which records will be selected. These fields normally represent the primary key in one table
and the corresponding foreign key in the other table.

Chapter 8 Java Database Connectivity (JDBC) 523
• If an SQL statement uses fields with the same name from multiple tables, the field names must be
fully qualified with its table name and a dot operator (.).
•An INSERT INTO statement inserts a new record in a table. The simplest form of this statement is
INSERT INTO tableName ( fieldName1, fieldName2, …, fieldNameN )
VALUES ( value1, value2, …, valueN )
where tableName is the table in which to insert the record. The tableName is followed by a com-
ma-separated list of field names in parentheses. The list of field names is followed by the SQL key-
word VALUES and a comma-separated list of values in parentheses.
• SQL statements use single quote (') as a delimiter for strings. To specify a string containing a sin-
gle quote in an SQL statement, the single quote must be escaped with another single quote.
•An UPDATE statement modifies data in a table. The simplest form for an UPDATE statement is
UPDATE tableName
SET fieldName1 = value1, fieldName2 = value2, …, fieldNameN = valueN
WHERE criteria
where tableName is the table in which to update a record (or records). The tableName is followed
by keyword SET and a comma-separated list of field name/value pairs in the format
fieldName = value. The WHERE clause criteria determines the record(s) to update.
•ADELETE statement removes data from a table. The simplest form for a DELETE statement is
DELETE FROM tableName WHERE criteria
where tableName is the table from which to delete a record (or records). The WHERE criteria de-
termines which record(s) to delete.
• Package java.sql contains classes and interfaces for manipulating relational databases in Java.
• A program must load the database driver class before the program can connect to the database.
• JDBC supports four categories of drivers: JDBC-to-ODBC bridge driver (Type 1); Native-API,
partly Java driver (Type 2); JDBC-Net pure Java driver (Type 3) and Native-Protocol pure Java
driver (Type 4). Type 3 and 4 drivers are preferred, because they are pure Java solutions.
• An object that implements interface Connection manages the connection between the Java pro-
gram and the database. Connection objects enable programs to create SQL statements that ma-
nipulate databases and to perform transaction processing.

• Method getConnection of class DriverManager attempts to connect to a database speci-
fied by its URL argument. The URL helps the program locate the database. The URL includes the
protocol for communication, the subprotocol for communication and the name of the database.
• Connection method createStatement creates an object of type Statement. The pro-
gram uses the Statement object to submit SQL statements to the database.
• Statement method executeQuery executes a query that selects information from a table or
set of tables and returns an object that implements interface ResultSet containing the query re-
sults. ResultSet methods enable a program to manipulate query results.
•AResultSetMetaData object describes a ResultSet’s contents. Programs can use meta-
data programmatically to obtain information about the ResultSet column names and types.
• ResultSetMetaData method getColumnCount retrieves the number of columns in the
ResultSet.
• ResultSet method next positions the ResultSet cursor to the next record in the Result-
Set. The cursor keeps track of the current record. Method next returns boolean value true

×