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

Chapter 10 Building Database Applications with JDBC

finally {

if(connection != null) connection.close(); if(resultSet != null) resultSet.close();

}

}

}

Run this program first.

Printing the contents of the table before inserting Starting to insert rows

Inserted row for Tom Inserted row for Dick Inserted row for Harry Table updation complete. . .

Rolling back to the state where Tom and Dick were inserted Printing the contents of the table after commit

1Tom

2Dick

Now let’s understand the program.

1.First you get the connection, create a statement, get a ResultSet, and print the contents of the table (which is empty).

2.You insert three rows, one after another. After inserting each row, you create a Savepoint object in that transaction. The first savepoint is an unnamed Savepoint after inserting “Tom” and the second and third are named savepoints occur after inserting “Dick” and “Harry.”

3.In the statement connection.rollback(secondSavepoint);, you instruct JDBC to roll back the transaction to the second savepoint. Remember that you’ve created the second savepoint to remember the state after inserting “Tom” and “Dick” but before inserting “Harry.” So the rollback is to the state where rows containing “Tom” and “Dick” are inserted.

4.The commit() method commits the current state of the transaction. Since the rollback is already called, the current state of the transaction is that there are two rows inserted containing the nicknames “Tom” and “Dick.” Printing the contents of the table confirms that it is indeed the case.

The RowSet Interface

The interface javax.sql.RowSet extends the ResultSet interface to provide support for the JavaBean component model. The RowSet interface defines getters and setters for different data types.

RowSet also supports methods to add and remove event listeners (since it is a JavaBean component). Other Java objects may use the event notification mechanism supported by RowSet. The RowSet interface implements the Observer design pattern (as a Subject). A Java object that wants to receive event notification from RowSet must implement the RowSetListner interface and must be registered with the RowSet object. RowSet notifies all the registered objects on the occurrence of one of the following events: change in cursor location, change in a row, and change in the entire RowSet object.

306

Chapter 10 Building Database Applications with JDBC

Java provides five different flavors of the RowSet interface (see Figure 10-3). The interfaces of these flavors can be found in the javax.sql.rowset package. The five interfaces are JdbcRowSet, JoinRowSet, CachedRowSet, WebRowSet, and FilteredRowSet. Java also offers a default reference implementation of these interfaces that can be found in

the com.sun.rowset package. These implementations are JdbcRowSetImpl, JoinRowSetImpl, CachedRowSetImpl, WebRowSetImpl, and FilteredRowSetImpl.

 

ResultSet

 

 

RowSet

 

 

 

ResultSet capabilities +

 

 

Java Bean capabilities +

JdbcRowSet

CachedRowSet

disconnected ResultSet

capabilities

 

 

ResultSet capabilities +

 

Capabilities supported

WebRowSet

by CachedRowSet + XML

Java Bean capabilities

 

capabilities

 

 

 

JoinRowSet

FilterRowSet

Capabilities supported

 

Capabilities supported

by WebRowSet + SOL

 

by WebRowSet +

join capabilities

 

filtering capabilities

Figure 10-3.  The RowSet hierarchy

JdbcRowSet is a connected RowSet, which means a JdbcRowSet implementation is always connected to the corresponding database. The other four interfaces are disconnected RowSets, which means an object of any one of these four RowSet implementations (except JdbcRowSet) connects to the database only when they want to read or write; all the other times they are disconnected from the database. This property of implementation of these four interfaces along with the capability of being serializable make them suitable for sending over the network.

Figure 10-3 shows the hierarchical relationship among various RowSet interfaces. As you already know, RowSet is a subinterface of the ResultSet interface. JdbcRowSet is a subinterface of RowSet; JdbcRowSet has all the features ResultSet supports plus Java Bean capabilities. CachedRowSet is also a subinterface of the RowSet interface; it has all the features JdbcRowSet supports plus it has the capabilities of a disconnected ResultSet. WebRowSet adds XML capabilities to the CachedRowSet features. Similarly, JoinRowSet adds SQL join capabilities to WebRowSet, and FilteredRowSet adds result filtering capabilities to WebRowSet.

Let’s now discuss the RowSetProvider class and the RowSetFactory interface, which were introduced in Java 7. RowSetProvider provides APIs to get a RowSetFactory implementation that can be used to instantiate a proper RowSet implementation. It provides the following two methods:

RowSetFactory newFactory(): This API creates a new instance of a RowSetFactory implementation. So which factory implementation will this method instantiate? It is a good question; the answer is that this API infers the type of factory implementation to instantiate from the environment settings. It first looks in the system property javax.sql. rowset.RowSetFactory. If the API could not infer the factory implementation, then it uses ServiceLoader API to determine the type of the factory implementation to instantiate, and

finally it looks for the platform default implementation of the RowSetFactory instance. If the API could not infer the factory implementation type, it raises a SQLException.

307

Chapter 10 Building dataBase appliCations with JdBC

RowSetFactory newFactory(String factoryClassName, ClassLoader classloader): If it is unclear which driver will be loaded when you call the plain newFactory() method due to multiple drivers in the scope, you can use the overloaded method newFactory(), which takes the class name of the factory and the class loader and instantiates the appropriate factory.

RowSetFactory defines five methods; each method creates a type of RowSet implementation. So why are RowSetFactory and RowSetProvider required to create a RowSet implementation when you can create them using the traditional plain way? The answer is flexibility; you can create the RowSet object without specifying the details that you need to provide during a traditional RowSet object; you can then set other details once the object gets created. How about writing a program to see how to use RowSetFactory and RowSetProvider? See Listing 10-13.

Listing 10-13. DbQuery5.java

import javax.sql.rowset.*; import java.sql.*;

// To illustrate how to use RowSet, RowSetProvider, and RowSetFactory class DbQuery5 {

public static void main(String[] args) {

String url = "jdbc:mysql://localhost:3306/addressBook"; String userName = "root";

String password = "mysql123"; try {

//first, create a factory object for rowset RowSetFactory rowSetFactory = RowSetProvider.newFactory();

//create a JDBC rowset from the factory

JdbcRowSet rowSet = rowSetFactory.createJdbcRowSet(); rowSet.setUrl(url);

rowSet.setUsername(userName);

rowSet.setPassword(password); rowSet.setCommand("SELECT * FROM contact"); rowSet.execute();

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

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

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

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

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

+rowSet.getString("phoneNo"));

}

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

}

}

}

It prints the following:

Id

fName

lName

email

phoneNo

1Michael Taylor michael@abc.com +919976543210

2William Becker william@abc.com +449876543210

3

Samuel Uncle

sam@abc.com

+119955331100

308

Chapter 10 Building Database Applications with JDBC

The output of the program is as expected. However, you made use of RowSetProvider and RowSetFactory. You first get the appropriate RowSetFactory and then create JdbcRowSet using the factory. The rest of the program is as you saw in Listing 10-3.

Points to Remember

Here are a few useful points that could be helpful in your OCPJP exam:

You can use column name or column index with ResultSet methods. The index you use is the index of the ResultSet object, not the column number in the database table.

A Statement object closes the current ResultSet object if a) the Statement object is closed, b) is re-executed, or c) is made to retrieve the next set of result. That means it is not necessary to call close() explicitly with ResultSet object; however, it is good practice to call close() once you are done with the object.

You may use the column name of a ResultSet object without worrying about the case: getXXX() methods accept case insensitive column names to retrieve the associated value.

Think of a case when you have two columns in a ResultSet object with the same name. How you can retrieve the associated values using the column name? If you use a column name to retrieve the value, it will always point to the first column that matches with the given name.

Hence, you have to use column index in this case to retrieve values associated with both columns.

You might remember that the PreparedStatement interface inherits from Statement. However, PreparedStatement overrides all flavors of execute() methods. For instance, the behavior of executeUpdate() might be different from its base method.

It is your responsibility to issue a correct SQL command; a JDBC Statement will not check for its correctness. For example, if there is a syntax error in the SQL command string, then you will not get a compiler error. Rather, you’ll get a MySQLSyntaxErrorException at runtime.

You may call the appropriate get() method immediately after inserting a row using the insertRow() method. However, the values of the row are undefined.

You may cancel any update you made using the method cancelRowUpdates(). However, you must call this method before calling the method updateRow(). In all other cases, it has no impact on the row.

While connecting to the database, you need to specify the correct username and password. If the provided username or password is not correct, you will get a SQLException.

JDBC 4.1 introduces the capability to use try-with-resources statement to close resources (Connection, ResultSet, and Statement) automatically.

309

Chapter 10 Building Database Applications with JDBC

Question Time!

1.Consider the following code segment. Assume that the connection object is valid and statement.executeQuery() method successfully returns a ResultSet object with a few rows in it.

Statement statement = connection.createStatement();

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

//from resultSet metadata, find out how many columns are there and then read the column entries

int numOfColumns = resultSet.getMetaData().getColumnCount(); while (resultSet.next()) {

//traverse the columns by index values

for(int i = 0; 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("");

}

Which of the following statements is true regarding this code segment?

A.The code segment will successfully print the contents of the rows in the ResultSet object.

B.The looping header is wrong. To traverse all the columns, it should be for(int i = 0; i <= numOfColumns; i++) {

C.The looping header is wrong. To traverse all the columns, it should be for(int i = 1; i <= numOfColumns; i++) {

D.The looping header is wrong. To traverse all the columns, it should be for(int i = 1; i < numOfColumns; i++) {

Answer: C. The looping header is wrong. To traverse all the columns, it should be

for(int i = 1; i <= numOfColumns; i++) {

(Given N columns in a table, the valid column indexes are from 1 to N and not 0 to N - 1.)

2.Assume that you’ve freshly created this table with the following command in MySQL:

create table familyGroup (id int not null auto_increment, nickName varchar(30) Not null, primary key (id));

You’ve written this program that makes use of this table:

import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement;

310

Chapter 10 Building Database Applications with JDBC

class DbTransactionTest {

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 familyGroup")) { resultSet.moveToInsertRow(); resultSet.updateString("nickName", "Sam");

resultSet.insertRow();

// INSERT

ROW

System.out.println("Table updated

with a row. . .");

connection.commit();

// COMMIT

STMT

}

}

}

What will be the result of executing this program assuming that establishing the connection succeeds?

A.The program will successfully insert a row with id = 1 and nickName = “Sam”.

B.A SQLException will be thrown in the line where the INSERT ROW comment is provided because you cannot insert a row on a read-only ResultSet object.

C.A SQLException will be thrown in the line where the COMMIT STMT statement is provided because auto-commit is enabled; hence the commit will fail.

D.The program will not insert anything into the familyGroup table.

Answer: C. A SQLException will be thrown in the line where the COMMIT STMT statement is provided because auto-commit is enabled; hence the commit will fail.

(Any attempt to use methods such as commit, rollback, setSavepoint, etc. will result in throwing a SQLException if auto-commit is not disabled.)

3.Consider the following sequence of operations in a transaction:

//assume that all operations execute in this program successfully without

//throwing any exceptions; also assume that the connection is established

//successfully

connection.setAutoCommit(false);

//insert a row into the table here

//create a savepoint in this transaction here

//insert another row into the table here

//create a named savepoint in this transaction here

//insert the third row into the table here

connection.rollback();

connection.commit(); 

311

Chapter 10 Building Database Applications with JDBC

What will be the effect of this sequence of actions after executing the statement connection.commit()?

A.Three rows will be inserted into the table.

B.No rows will be inserted into the table.

C.One row will be inserted into the table.

D.Two rows will be inserted into the table.

E.All three rows will be inserted into the table. Answer: B. No rows will be inserted into the table.

(Since connection.rollback(); is called before connection.commit(), all operations will be undone and no rows will be inserted into the table.)

4.Which one of the following statements would be needed in JDBC 3.0?

A.Connection connection = DriverManager.getConnection("jdbc:mysql:// localhost:3306/addressBook", "root", "password"))

B.Connection connection = DriverManager.createConnection("jdbc:mysql:// localhost:3306/addressBook", "root", "password"))

C.Class.forName("com.mysql.jdbc.Driver").newInstance();

D.Class.forName("com.mysql.jdbc.Driver").getInstance();

Answer: C. Class.forName("com.mysql.jdbc.Driver").newInstance();

(You need to explicitly load the JDBC driver using the Class.forName() statement in JDBC 3.0. From 4.0 onwards, this statement is not needed and you can directly get the connection. Note that option A) shows how to get the connection for MySQL, and this URl will depend on the specific database used.)

5.Consider this program and choose the best option describing its behavior (assume that the connection is valid):

try (Statement statement = connection.createStatement();

ResultSet resultSet = statement.executeQuery("SELECT * FROM contact")){ System.out.println(resultSet.getInt("id") + "\t"

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

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

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

+resultSet.getString("phoneNo"));

}

catch (SQLException sqle) { System.out.println("SQLException");

}

A.This program will print the following: SQLException.

B.This program will print the first row from contact.

C.This program will print all the rows from contact.

D.This program will report compiler errors.

Answer: A. This program will print the following: SQLException.

312

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