Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Ganesh_JavaSE7_Programming_1z0-804_study_guide.pdf
Скачиваний:
94
Добавлен:
02.02.2015
Размер:
5.88 Mб
Скачать

Chapter 10 Building Database Applications with JDBC

ResultSet also provides a set of methods to read the value at the desired column in the current row. In general, these methods come in two flavors: the first flavor takes column number as the input and the second flavor accepts column name as the input. For instance, the methods to read a double value are double getDouble(int columnNumber) and double getDouble(String columnName). In a similar way, ResultSet provides get() methods for all basic types.

Similarly, ResultSet provides a set of methods to update values at the desired column in the selected row. These methods also come in two variants: void updateXXX(int columnNumber, XXX x) and void updateXXX(String columnName, XXX x), where the update methods are defined for various data types represented as XXX.

Querying the Database

Now you know all the necessary interfaces that will be used to execute a simple SQL query on a database: Connection, Statement, and ResultSet. Let’s query a database and print the output. Recollect that you have created a database named addressBook and a table named contact within this database, and inserted two rows within the table. Assume that you want to print the table contents; Listings 10-2 and 10-3 contain the program to do so.

Listing 10-2.  DbConnector.java

import java.sql.*;

// Utility class with method connectToDb() that will be used by other programs in this chapter public class DbConnector {

public static Connection connectToDb() throws SQLException { String url = "jdbc:mysql://localhost:3306/";

String database = "addressBook"; String userName = "root"; String password = "mysql123";

return DriverManager.getConnection(url + database, userName, password);

}

}

Listing 10-3.  DbQuery.java

import java.sql.*;

// Program to illustrate how to query a database class DbQuery {

public static void main(String[] args) {

//Get connection, execute query, get the result set

//and print the entries from the result rest

try (Connection connection = DbConnector.connectToDb(); Statement statement = connection.createStatement();

ResultSet resultSet = statement.executeQuery("SELECT * FROM contact")){ System.out.println("ID \tfName \tlName \temail \t\tphoneNo");

while (resultSet.next()) { System.out.println(resultSet.getInt("id") + "\t"

+resultSet.getString("firstName") + "\t"

+resultSet.getString("lastName") + "\t"

+resultSet.getString("email") + "\t"

+resultSet.getString("phoneNo"));

}

}

290

Chapter 10 Building Database Applications with JDBC

catch (SQLException sqle) { sqle.printStackTrace(); System.exit(−1);

}

}

}

The output of the program is

 

 

 

 

ID

fName

lName

email

phoneNo

1Michael Taylor michael@abc.com +919876543210

2William Becker william@abc.com +449876543210

Let’s have a look at what is happening in this code snippet step by step.

In the main() method, there is a try-with-resources statement. The first statement is a call to the connectToDb() method, which is defined in the program. The connectToDb() method simply connects to the database (which you saw in the last example) and returns a Connection object if it succeeds.

In the next statement, you create a Statement object from the connection.

The Statement object is now used to execute a query. You want to fetch all the columns in the contact table; hence you write SELECT * FROM contact as a SQL query. You execute the query using the executeQuery() method of the statement object. The outcome of the query is stored in a ResultSet object.

Now this ResultSet object is used to print the fetched data. You read all column values in the current row and you do the same for each row in the ResultSet object.

Since you’ve created the Connection, Statement, and ResultSet objects within a try-with- resources statement, there is no need to explicitly call close() on these resources. However, if you are not using try-with-resources, you need to release them explicitly in a finally block.

Here, you are using column names to read the associated values. You can use column numbers instead to do the same job. Here is the modified code inside the while loop to use column numbers instead:

while (resultSet.next()) { System.out.println(resultSet.getInt(1)

+"\t" + resultSet.getString(2)

+"\t" + resultSet.getString(3)

+"\t" + resultSet.getString(4)

+"\t" + resultSet.getString(5));

}

This code produces exactly the same result as the last example. However, one important thing to observe here is that column index starts from 1, not from 0.

 The column index in the ResultSet object starts from 1, not from 0.

291

Chapter 10 Building Database Applications with JDBC

Here, while referring to columns by column index, if you refer to a column by an index that is more than the total number of columns, you will get an exception. For instance, if you change one of the column indices used in the last example to 6, you will get the following exception:

java.sql.SQLException: Column Index out of range, 6 > 5.

at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1074) [. . . this part of the stack trace elided . . .]

at DbQuery.main(DbQuery.java:18)

Hence, you should be careful and always provide the correct column indices.

In this example, you know the number of columns as well as the data types in columns. What if you neither know the number of columns in each row nor the data types in the columns? You can use the getMetaData() method and use the getColumnCount() method to get the column count. When you don’t know the data type of a column entry, you can just use the getObject() method on the ResultSet object. Here is the modified code that makes use of these methods:

// from resultSet metadata, find out how many columns are there and then read the column entries int numOfColumns = resultSet.getMetaData().getColumnCount();

while (resultSet.next()) {

// remember that the column index starts from 1 not 0 for(int i = 1; i <= numOfColumns; i++) {

// since we do not know the data type of the column, we use getObject() System.out.print(resultSet.getObject(i) + "\t");

}

System.out.println("");

}

The output of the program remains the same, so we haven’t shown the resulting output here.

Okay, let’s carry out another exercise. This time you just want to print the name and e-mail address where the first name matches to “Michael.” See Listing 10-4.

Listing 10-4.  DbQuery4.java

import java.sql.*;

class DbQuery4 {

public static void main(String[] args) throws SQLException { try (Connection connection = DbConnector.connectToDb();

Statement statement = connection.createStatement();

ResultSet resultset = statement.executeQuery("SELECT firstName, email FROM contact WHERE firstName=\"Michael\"")) {

System.out.println("fName \temail"); while (resultset.next()){

System.out.println(resultset.getString("firstName") + "\t" + resultset.getString("email"));

}

} catch (SQLException e) { e.printStackTrace(); System.exit(−1);

}

}

}

292

4

Chapter 10 Building Database Applications with JDBC

It prints:

fName email

Michael michael@abc.com

Updating the Database

Now let’s update the database. You can update a database in two ways: you can use SQL queries to update the database directly, or you can fetch a ResultSet using a SQL query and then you can change the ResultSet and the database. JDBC supports both of these methods. Let’s focus on retrieving the ResultSet and modifying the ResultSet and the database.

In order to modify the ResultSet and the database, the ResultSet class provides a set of update methods for each data type. Also, there are other supporting methods such as updateRow() and deleteRow() to make the task simpler. It’s time to get your hands dirty: assume that one of your contacts in your addressBook database has changed his phone number, so you are now going to update his phone number in your database using a JDBC program.

Listing 10-5.  DbUpdate.java

import java.sql.*;

// To illustrate how we can update a database class DbUpdate {

public static void main(String[] args) throws SQLException { try (Connection connection = DbConnector.connectToDb();

Statement statement = connection.createStatement();

ResultSet resultSet = statement.executeQuery("SELECT * FROM contact WHERE firstName=\"Michael\"")) {

// first fetch the data and display it before the update operation System.out.println("Before the update");

System.out.println("id \tfName \tlName \temail \t\tphoneNo"); while (resultSet.next()) {

System.out.println(resultSet.getInt("id") + "\t"

+resultSet.getString("firstName") + "\t"

+resultSet.getString("lastName") + "\t"

+resultSet.getString("email") + "\t"

+resultSet.getString("phoneNo"));

}

// now update the resultSet and display the modified data resultSet.absolute(1);

resultSet.updateString("phoneNo", "+919976543210"); System.out.println("After the update"); System.out.println("id \tfName \tlName \temail \t\tphoneNo"); resultSet.beforeFirst();

while (resultSet.next()) { System.out.println(resultSet.getInt("id") + "\t"

+resultSet.getString("firstName") + "\t"

+resultSet.getString("lastName") + "\t"

+resultSet.getString("email") + "\t"

+resultSet.getString("phoneNo"));

}

293

Chapter 10 Building Database Applications with JDBC

} catch (SQLException e) { e.printStackTrace(); System.exit(−1);

}

}

}

Let’s pick out the nitty-gritty of the program step by step:

You establish the connection using the DbConnector.connectToDb() method.

After creating a Statement object, you execute a query on the database to find out the record associated with Michael. (For the sake of simplicity we are assuming that the ResultSet will contain exactly one record.)

You print the retrieved record.

You use the absolute() method to move the cursor to the first row in the ResultSet object; then you update the phone number using the updateString() method.

And finally you print the modified resultset.

Well, that looks straightforward. Now, execute it and see what this program prints:

Before the

update

 

 

id

fName

lName

email

phoneNo

1

Michael Taylor

michael@abc.com

+919876543210

com.mysql.jdbc.NotUpdatable: Result Set

not updatable.(. . .rest of the text elided)

 

at

com.mysql.jdbc.ResultSetImpl.updateString(ResultSetImpl.java:8618)

 

at

com.mysql.jdbc.ResultSetImpl.updateString(ResultSetImpl.java:8636)

 

at

DbUpdate.main(DbUpdate.java:34)

 

 

 

 

 

Oops, the program crashed after throwing an exception! What happened?

You are trying to update a ResultSet object that is not updatable. In other words, in order to make the update in the ResultSet and the database, you need to make this ResultSet updatable. You can do that by creating a proper Statement object; while calling the createStatement() method you can pass inputs such as whether you want a scrollable ResultSet that is sensitive to changes or you want an updatable ResultSet.

So, make this one single change to the call to the createStatement() method in Listing 10-5:

Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_ UPDATABLE);

Now run this changed program to see if it works.

 

 

 

 

Before the update

 

 

id

fName

lName

email

phoneNo

1

Michael

Taylor

michael@abc.com

+919876543210

After the update

 

 

 

id

fName

lName

email

phoneNo

1

Michael

Taylor

michael@abc.com

+919876543210

 

 

 

 

Good, the program did not result in any exception. But wait, the phone number of Michael is not updated! What happened? You forgot a vital statement after the update: the updateRow() method. Every time you make change in ResultSet using the appropriate updateXXX() method, you need to call updateRow() to make sure that all the values are actually updated in the database. Make this change and try again (see Listing 10-6).

294

Chapter 10 Building Database Applications with JDBC

Listing 10-6.  DbUpdate2.java

import java.sql.*;

// To illustrate how we can update a database class DbUpdate2 {

public static void main(String[] args) throws SQLException { try (Connection connection = DbConnector.connectToDb();

//create a statement from which the created ResultSets

//are "scroll sensitive" as well as "updatable" Statement statement =

connection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);

ResultSet resultSet = statement.executeQuery("SELECT * FROM contact WHERE firstName=\"Michael\"")) {

//first fetch the data and display it before the update operation System.out.println("Before the update");

System.out.println("id \tfName \tlName \temail \t\tphoneNo"); while (resultSet.next()) {

System.out.println(resultSet.getInt("id") + "\t"

+resultSet.getString("firstName") + "\t"

+resultSet.getString("lastName") + "\t"

+resultSet.getString("email") + "\t"

+resultSet.getString("phoneNo"));

}

//now update the resultSet and display the modified data resultSet.absolute(1);

resultSet.updateString("phoneNo", "+919976543210");

//reflect those changes back to the database by calling updateRow() method resultSet.updateRow();

System.out.println("After the update"); System.out.println("id \tfName \tlName \temail \t\tphoneNo"); resultSet.beforeFirst();

while (resultSet.next()) { System.out.println(resultSet.getInt("id") + "\t"

+resultSet.getString("firstName") + "\t"

+resultSet.getString("lastName") + "\t"

+resultSet.getString("email") + "\t"

+resultSet.getString("phoneNo"));

}

} catch (SQLException e) { e.printStackTrace(); System.exit(−1);

}

}

}

 

 

 

 

 

Now this program prints the following:

 

 

 

 

 

Before the update

 

 

id

fName

lName

email

phoneNo

1

Michael Taylor

michael@abc.com

+919876543210

295

Chapter 10 Building Database Applications with JDBC

After the update

 

 

 

id

fName

lName

email

phoneNo

1

Michael

Taylor

michael@abc.com

+919976543210

 

 

 

 

Yes, it is working fine now. Now you know the requirements and steps required to update a row in a database.

 Always call updateRow() after modifying the row contents; otherwise you will lose the changes.

Next, how about inserting a record in the RecordSet and the database? Try the next example, shown in Listing 10-7.

Listing 10-7.  DbInsert.java

import java.sql.*;

// To illustrate how to insert a row in a ResultSet and in the database class DbInsert {

public static void main(String[] args) throws SQLException { try (Connection connection = DbConnector.connectToDb(); Statement statement = connection.createStatement(

ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet resultSet = statement.executeQuery("SELECT * FROM contact")) { System.out.println("Before the insert");

System.out.println("id \tfName \tlName \temail \t\tphoneNo"); while (resultSet.next()){

System.out.println(resultSet.getInt("id") + "\t"

+resultSet.getString("firstName") + "\t"

+resultSet.getString("lastName") + "\t"

+resultSet.getString("email") + "\t"

+resultSet.getString("phoneNo"));

}

resultSet.moveToInsertRow(); resultSet.updateString("firstName", "John"); resultSet.updateString("lastName", "K."); resultSet.updateString("email", "john@abc.com"); resultSet.updateString("phoneNo", "+19753186420"); resultSet.insertRow();

System.out.println("After the insert"); System.out.println("id \tfName \tlName \temail \t\tphoneNo"); resultSet.beforeFirst();

while (resultSet.next()){ System.out.println(resultSet.getInt("id") + "\t"

+resultSet.getString("firstName") + "\t"

+resultSet.getString("lastName") + "\t"

+resultSet.getString("email") + "\t"

+resultSet.getString("phoneNo"));

}

296

Chapter 10 Building Database Applications with JDBC

} catch (SQLException e) { e.printStackTrace();

}

}

}

What happened in this example? After printing the current records, you call the moveToInsertRow() method. This method sets the cursor to a new record and prepares the ResultSet for the insertion of a row (creates a buffer to hold the column values). After it, you use the updateString() method to modify each column value in the newly added row. And finally, you call insertRow() to finally insert the new row into the ResultSet and the database.

One important thing to note here is that you need to provide correct types of values for each column. Also, you cannot leave a column blank (i.e., not provide any value) if the column value can not be left unfilled. In both of these violations, you may get a SQLException.

Let’s see what this program prints.

 

 

 

 

Before the insert

 

 

id

fName

lName

email

phoneNo

1Michael Taylor michael@abc.com +919976543210

2William Becker william@abc.com +449876543210 After the insert

id

fName

lName

email

phoneNo

1Michael Taylor michael@abc.com +919976543210

2William Becker william@abc.com +449876543210

3

John

K.

john@abc.com

+19753186420

 

 

 

 

Looks good! Now let’s try another operation: delete a record from the database. Take a look at the program in Listing 10-8.

Listing 10-8.  DbDelete.java

import java.sql.*;

// To illustrate how to delete a row in a ResultSet and in the database class DbDelete {

public static void main(String[] args) throws SQLException { try (Connection connection = DbConnector.connectToDb();

Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);

ResultSet resultSet1 = statement.executeQuery

("SELECT * FROM contact WHERE firstName=\"John\"")) { if(resultSet1.next()){

// delete the first row resultSet1.deleteRow();

}

resultSet1.close();

// now fetch again from the database try (ResultSet resultSet2 =

statement.executeQuery("SELECT * FROM contact")) {

297

Chapter 10 Building dataBase appliCations with JdBC

System.out.println("After the deletion"); System.out.println("id \tfName \tlName \temail \t\tphoneNo"); while (resultSet2.next()){

System.out.println(resultSet2.getInt("id") + "\t"

+resultSet2.getString("firstName") + "\t"

+resultSet2.getString("lastName") + "\t"

+resultSet2.getString("email") + "\t"

+resultSet2.getString("phoneNo"));

}

}

} catch (SQLException e) { e.printStackTrace(); System.exit(−1);

}

}

}

This program simply selects a proper row to delete and calls the deleteRow() method on the current selected row. Here’s the output of the program:

After the deletion

 

 

id

fName

lName

email

phoneNo

1Michael Taylor michael@abc.com +919976543210

2William Becker william@abc.com +449876543210

Well, the program works fine and correctly removes the row where the first name of the person is “John.” You might have remembered that you have created a table named contact in your database to work with.

At that time, you created that table from the MySQL command prompt. The same task could have been done through a JDBC program. At this juncture, let’s create a new table named familyGroup in the database programmatically (see Listing 10-9). You will use this table later in this chapter.

Listing 10-9. DbCreateTable.java

import java.sql.*; class DbCreateTable {

public static void main(String[] args) {

try (Connection connection = DbConnector.connectToDb(); Statement statement = connection.createStatement()){

// use CREATE TABLE SQL statement to create table familyGroup

int result = statement.executeUpdate("CREATE TABLE familyGroup (id int not null auto_increment, nickName varchar(30) not null, primary key(id));"); System.out.println("Table created successfully");

}

catch (SQLException sqle) { sqle.printStackTrace(); System.exit(−1);

}

}

}

298

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]