32
Enterprise Java Jan-June 2014 Prepared by: Mr. Hitesh Kumar Sharma & Mr. Ravi Tomar Page 1 To be submitted by: B.Tech CS VI Sem (MFT+O&G+OSS+CCVT) LECTURE NOTES Unit 2: Working with Database: JDBC Introduction of JDBC Types of Drivers Two-Tier Client/Server Model Three-Tier Client/Server Model Basic Steps of JDBC Statement, Prepared Statement, Callable Statement. Insertion, Deletion and Updation using JDBC Working with Resultsets, Selectable, Updateable and Holdable Resultsets

Introduction to JDBC and JDBC Drivers

  • Upload
    kumar

  • View
    116

  • Download
    2

Embed Size (px)

Citation preview

Page 1: Introduction to JDBC and JDBC Drivers

Enterprise Java Jan-June 2014

Prepared by: Mr. Hitesh Kumar Sharma & Mr. Ravi Tomar Page 1 To be submitted by: B.Tech CS VI Sem (MFT+O&G+OSS+CCVT)

LECTURE NOTES Unit 2: Working with Database: JDBC

Introduction of JDBC

Types of Drivers

Two-Tier Client/Server Model

Three-Tier Client/Server Model

Basic Steps of JDBC

Statement, Prepared Statement, Callable Statement.

Insertion, Deletion and Updation using JDBC

Working with Resultsets, Selectable, Updateable and Holdable Resultsets

Page 2: Introduction to JDBC and JDBC Drivers

Enterprise Java Jan-June 2014

Prepared by: Mr. Hitesh Kumar Sharma & Mr. Ravi Tomar Page 2 To be submitted by: B.Tech CS VI Sem (MFT+O&G+OSS+CCVT)

1. INTRODUCTION TO JDBC: JAVA DATA BASE CONNECTIVITY

The Java JDBC API enables Java applications to connect to relational databases via a standard API, so your Java applications become independent (almost) of the database the application uses.

Java application using JDBC to connect to a database.

JDBC standardizes how to connect to a database, how to execute queries against it, how to navigate the result of such a query, and how to exeucte updates in the database. JDBC does not standardize the SQL sent to the database. This may still vary from database to database.

The JDBC API consists of the following core parts:

JDBC Drivers

Connections

Statements

Result Sets

There are four basic JDBC use cases around which most JDBC work evolves:

Query the database (read data from it).

Query the database meta data.

Update the database.

Perform transactions.

Page 3: Introduction to JDBC and JDBC Drivers

Enterprise Java Jan-June 2014

Prepared by: Mr. Hitesh Kumar Sharma & Mr. Ravi Tomar Page 3 To be submitted by: B.Tech CS VI Sem (MFT+O&G+OSS+CCVT)

1.1. Core JDBC Components 1.1.1.JDBC Drivers

A JDBC driver is a collection of Java classes that enables you to connect to a certain database. For instance, MySQL will have its own JDBC driver. A JDBC driver implements a lot of the JDBC interfaces. When your code uses a given JDBC driver, it actually just uses the standard JDBC interfaces. The concrete JDBC driver used is hidden behind the JDBC interfaces. Thus you can plugin a new JDBC driver without your code noticing it. 1.1.2. Connections

Once a JDBC driver is loaded and initialized, you need to connect to the database. You do so by obtaining a Connection to the database via the JDBC API and the loaded driver. All communication with the database happens via a connection. An application can have more than one connection open to a database at a time. This is actually very common. 1.1.3. Statements

A Statement is what you use to execute queries and updates against the database. There are a few different types of statements you can use. Each statement corresponds to a single query or update.

1.1.4. ResultSet

When you perform a query against the database you get back a ResultSet. You can then traverse this ResultSetto read the result of the query.

Page 4: Introduction to JDBC and JDBC Drivers

Enterprise Java Jan-June 2014

Prepared by: Mr. Hitesh Kumar Sharma & Mr. Ravi Tomar Page 4 To be submitted by: B.Tech CS VI Sem (MFT+O&G+OSS+CCVT)

An Example Diagram

Here is an example of how the core components interact in during the execution of a database query .

Java JDBC: Interaction of the core JDBC components during the execution of a database query.

Page 5: Introduction to JDBC and JDBC Drivers

Enterprise Java Jan-June 2014

Prepared by: Mr. Hitesh Kumar Sharma & Mr. Ravi Tomar Page 5 To be submitted by: B.Tech CS VI Sem (MFT+O&G+OSS+CCVT)

JDBC DRIVER TYPES:

A JDBC driver is a set of Java classes that implement the JDBC interfaces, targeting a specific database. The JDBC interfaces comes with standard Java, but the implementation of these interfaces is specific to the database you need to connect to. Such an implementation is called a JDBC driver.

There are 4 different types of JDBC drivers:

Type 1: JDBC-ODBC bridge driver

Type 2: Java + Native code driver

Type 3: All Java + Middleware translation driver

Type 4: All Java driver.

Today, most drivers are type 4 drivers. 2.1. Type 1 JDBC Driver

A type 1 JDBC driver consists of a Java part that translates the JDBC interface calls to ODBC calls. An ODBC bridge then calls the ODBC driver of the given database. Type 1 drivers are (were) mostly intended to be used in the beginning, when there were no type 4 drivers (all Java drivers). Here is an illustration of how a type 1 JDBC driver is organized:

Type 1 JDBC driver.

2.2. Type 2 JDBC Driver

A type 2 JDBC driver is like a type 1 driver, except the ODBC part is replaced with a native code part instead. The native code part is targeted at a specific database product. Here is an illustration of a type 2 JDBC driver:

Page 6: Introduction to JDBC and JDBC Drivers

Enterprise Java Jan-June 2014

Prepared by: Mr. Hitesh Kumar Sharma & Mr. Ravi Tomar Page 6 To be submitted by: B.Tech CS VI Sem (MFT+O&G+OSS+CCVT)

Type 2 JDBC driver.

2.3. Type 3 JDBC Driver

A type 3 JDBC driver is an all Java driver that sends the JDBC interface calls to an intermediate server. The intermediate server then connects to the database on behalf of the JDBC driver. Here is an illustration of a type 3 JDBC driver:

Type 3 JDBC driver.

2.4. Type 4 JDBC Driver

A type 4 JDBC driver is an all Java driver which connects directly to the database. It is implemented for a specific database product. Today, most JDBC drivers are type 4 drivers. Here is an illustration of how a type 4 JDBC driver is organized:

Type 4 JDBC driver.

2.5. JDBC: Open Database Connection

Before you can read or write data in a database via JDBC, you need to open a connection to the database. This text will show you how to do that.

Loading the JDBC Driver

The first thing you need to do before you can open a database connection is to load the JDBC driver for the database. Actually, from Java 6 this is no longer necessary, but doing so will not fail. You load the JDBC driver like this:

Page 7: Introduction to JDBC and JDBC Drivers

Enterprise Java Jan-June 2014

Prepared by: Mr. Hitesh Kumar Sharma & Mr. Ravi Tomar Page 7 To be submitted by: B.Tech CS VI Sem (MFT+O&G+OSS+CCVT)

Class.forName("driverClassName");

You only have to load the driver once. You do not need to load it before every connection opened. Only before the first connection opened.

Opening the Connection

To open a database connection you use the java.sql.DriverManager class. You call its getConnection() method, like this:

String url = "jdbc:h2:~/test"; //database specific url. String user = "sa"; String password = ""; Connection connection =DriverManager.getConnection(url, user, password);

The url is the url to your database. You should check the documentation for your database and JDBC driver to see what the format is for your specific database. The url shown above is for a H2Database. The user and password parameters are the user name and password for your database.

Closing the Connection

Once you are done using the database connection you should close it. This is done by calling the Connection.close() method, like this:

connection.close();

JDBC: Query the Database

Querying a database means searching through its data. You do so be sending SQL statements to the database. To do so, you first need an open database connection. Once you have an open connection, you need to create a Statementobject, like this:

Statement statement = connection.createStatement();

Once you have created the Statement you can use it to execute SQL queries, like this:

String sql = "select * from people";

Page 8: Introduction to JDBC and JDBC Drivers

Enterprise Java Jan-June 2014

Prepared by: Mr. Hitesh Kumar Sharma & Mr. Ravi Tomar Page 8 To be submitted by: B.Tech CS VI Sem (MFT+O&G+OSS+CCVT)

ResultSet result = statement.executeQuery(sql);

When you execute an SQL query you get back a ResultSet. The ResultSet contains the result of your SQL query. The result is returned in rows with columns of data. You iterate the rows of the ResultSet like this:

while(result.next()) { String name = result.getString("name"); long age = result.getLong ("age"); }

The ResultSet.next() method moves to the next row in the ResultSet, if there are any more rows. If there are anymore rows, it returns true. If there were no more rows, it will return false. You need to call next() at least one time before you can read any data. Before the first next() call the ResultSetis positioned before the first row.You can get column data for the current row by calling some of the getXXX() methods, where XXX is a primitive data type. For instance:

result.getString ("columnName"); result.getLong ("columnName"); result.getInt ("columnName"); result.getDouble ("columnName"); result.getBigDecimal("columnName"); etc.

The column name to get the value of is passed as parameter to any of these getXXX() method calls. You can also pass an index of the column instead, like this:

result.getString (1); result.getLong (2); result.getInt (3); result.getDouble (4); result.getBigDecimal(5); etc.

For that to work you need to know what index a given column has in the ResultSet. You can get the index of a given column by calling the ResultSet.findColumn() method, like this:

int columnIndex = result.findColumn("columnName");

Page 9: Introduction to JDBC and JDBC Drivers

Enterprise Java Jan-June 2014

Prepared by: Mr. Hitesh Kumar Sharma & Mr. Ravi Tomar Page 9 To be submitted by: B.Tech CS VI Sem (MFT+O&G+OSS+CCVT)

If iterating large amounts of rows, referencing the columns by their index might be faster than by their name. When you are done iterating the ResultSet you need to close both the ResultSet and the Statement object that created it (if you are done with it, that is). You do so by calling their close() methods, like this:

result.close(); statement.close();

Of course you should call these mehtods inside a finally block to make sure that they are called even if an exception occurs during ResultSet iteration. Full Example

Here is a full query code example:

Statement statement = connection.createStatement(); String sql = "select * from people"; ResultSet result = statement.executeQuery(sql); while(result.next()) { String name = result.getString("name"); long age = result.getLong("age"); System.out.println(name); System.out.println(age); } result.close(); statement.close(); And here the example ResultSet result = statement.executeQuery(sql); while(result.next()) { String name = result.getString("name"); long age = result.getLong("age"); System.out.println(name); System.out.println(age); }

with try-finally blocks added. Notice, left out the catch blocks to make the example shorter.

Statement statement = null; try{ statement = connection.createStatement(); ResultSet result = null;

try{

String sql = "select * from people";

Page 10: Introduction to JDBC and JDBC Drivers

Enterprise Java Jan-June 2014

Prepared by: Mr. Hitesh Kumar Sharma & Mr. Ravi Tomar Page 10 To be submitted by: B.Tech CS VI Sem (MFT+O&G+OSS+CCVT)

} finally { if(result != null) result.close(); } } finally { if(statement != null) statement.close(); }

JDBC Update the Database

In order to update the database you need to use a Statement. But, instead of calling the executeQuery()method, you call the executeUpdate() method.

There are two types of updates you can perform on a database:

1. Update record values

2. Delete records The executeUpdate() method is used for both of these types of updates. Updating Records

Here is an update record value example:

Statement statement = connection.createStatement(); String sql = "update people set name='John' where id=123"; int rowsAffected = statement.executeUpdate(sql);

The rowsAffected returned by the statement.executeUpdate(sql) call, tells how many records in the database were affected by the SQL statement. Deleting Records

Here is a delete record example:

Statement statement = connection.createStatement(); String sql = "delete from people where id=123"; int rowsAffected = statement.executeUpdate(sql);

Again, the rowsAffected returned by the statement.executeUpdate(sql) call, tells how many records in the database were affected by the SQL statement.

Page 11: Introduction to JDBC and JDBC Drivers

Enterprise Java Jan-June 2014

Prepared by: Mr. Hitesh Kumar Sharma & Mr. Ravi Tomar Page 11 To be submitted by: B.Tech CS VI Sem (MFT+O&G+OSS+CCVT)

3. JDBC: PREPAREDSTATEMENT

A PreparedStatement is a special kind of Statement object with some useful features. Remember, you need aStatement in order to execute either a query or an update. You can use a PreparedStatement instead of aStatement and benefit from the features of the PreparedStatement.

The PreparedStatement's primary features are:

Easy to insert parameters into the SQL statement.

Easy to reuse the PreparedStatement with new parameters.

May increase performance of executed statements.

Enables easier batch updates. We will show you how to insert parameters into SQL statements in this text, and also how to reuse a PreparedStatement. The batch updates is explained in a separate text.

Here is a quick example, to give you a sense of how it looks in code:

String sql = "update people set firstname=? , lastname=? where id=?"; PreparedStatement preparedStatement = connection.prepareStatement(sql); preparedStatement.setString(1, "Gary"); preparedStatement.setString(2, "Larson"); preparedStatement.setLong (3, 123); int rowsAffected = preparedStatement.executeUpdate();

3.1. Creating a PreparedStatement

Before you can use a PreparedStatement you must first create it. You do so using theConnection.prepareStatement(), like this:

String sql = "select * from people where id=?"; PreparedStatement preparedStatement = connection.prepareStatement(sql);

Page 12: Introduction to JDBC and JDBC Drivers

Enterprise Java Jan-June 2014

Prepared by: Mr. Hitesh Kumar Sharma & Mr. Ravi Tomar Page 12 To be submitted by: B.Tech CS VI Sem (MFT+O&G+OSS+CCVT)

The PreparedStatement is now ready to have parameters inserted.

3.2. Inserting Parameters into a PreparedStatement

Everywhere you need to insert a parameter into your SQL, you write a question mark (?). For instance:

String sql = "select * from people where id=?";

Once a PreparedStatement is created (prepared) for the above SQL statement, you can insert parameters at the location of the question mark. This is done using the many setXXX() methods. Here is an example:

preparedStatement.setLong(1, 123);

The first number (1) is the index of the parameter to insert the value for. The second number (123) is the value to insert into the SQL statement.

Here is the same example with a bit more details:

String sql = "select * from people where id=?"; PreparedStatement preparedStatement = connection.prepareStatement(sql); preparedStatement.setLong(123);

You can have more than one parameter in an SQL statement. Just insert more than one question mark. Here is a simple example:

String sql = "select * from people where firstname=? and lastname=?"; PreparedStatement preparedStatement = connection.prepareStatement(sql); preparedStatement.setString(1, "John"); preparedStatement.setString(2, "Smith");

Executing the PreparedStatement

Executing the PreparedStatement looks like executing a regular Statement. To execute a query, call theexecuteQuery() or executeUpdate method. Here is an executeQuery() example:

String sql = "select * from people where firstname=? and lastname=?";

Page 13: Introduction to JDBC and JDBC Drivers

Enterprise Java Jan-June 2014

Prepared by: Mr. Hitesh Kumar Sharma & Mr. Ravi Tomar Page 13 To be submitted by: B.Tech CS VI Sem (MFT+O&G+OSS+CCVT)

PreparedStatement preparedStatement = connection.prepareStatement(sql); preparedStatement.setString(1, "John"); preparedStatement.setString(2, "Smith"); ResultSet result = preparedStatement.executeQuery();

As you can see, the executeQuery() method returns a ResultSet. Iterating the ResultSet is described in theQuery the Database text.

Here is an executeUpdate() example:

String sql = "update people set firstname=? , lastname=? where id=?"; PreparedStatement preparedStatement = connection.prepareStatement(sql); preparedStatement.setString(1, "Gary"); preparedStatement.setString(2, "Larson"); preparedStatement.setLong (3, 123); int rowsAffected = preparedStatement.executeUpdate();

The executeUpdate() method is used when updating the database. It returns an int which tells how many records in the database were affected by the update. 3.3. Reusing a PreparedStatement

Once a PreparedStatement is prepared, it can be reused after execution. You reuse a PreparedStatement by setting new values for the parameters and then execute it again. Here is a simple example:

String sql = "update people set firstname=? , lastname=? where id=?"; PreparedStatement preparedStatement = connection.prepareStatement(sql); preparedStatement.setString(1, "Gary"); preparedStatement.setString(2, "Larson"); preparedStatement.setLong (3, 123); int rowsAffected = preparedStatement.executeUpdate(); preparedStatement.setString(1, "Stan"); preparedStatement.setString(2, "Lee"); preparedStatement.setLong (3, 456); int rowsAffected = preparedStatement.executeUpdate();

This works for executing queries too, using the executeQuery() method, which returns a ResultSet.

Page 14: Introduction to JDBC and JDBC Drivers

Enterprise Java Jan-June 2014

Prepared by: Mr. Hitesh Kumar Sharma & Mr. Ravi Tomar Page 14 To be submitted by: B.Tech CS VI Sem (MFT+O&G+OSS+CCVT)

3.4. PreparedStatement Performance

It takes time for a database to parse an SQL string, and create a query plan for it. A query plan is an analysis of how the database can execute the query in the most efficient way.

If you submit a new, full SQL statement for every query or update to the database, the database has to parse the SQL and for queries create a query plan. By reusing an existing PreparedStatement you can reuse both the SQL parsing and query plan for subsequent queries. This speeds up query execution, by decreasing the parsing and query planning overhead of each execution.

There are two levels of potential reuse for a PreparedStatement.

1. Reuse of PreparedStatement by the JDBC driver.

2. Reuse of PreparedStatement by the database.

First of all, the JDBC driver can cache PreparedStatement objects internally, and thus reuse thePreparedStatement objects. This may save a little of the PreparedStatement creation time.

Second, the cached parsing and query plan could potentially be reused across Java applications, for instance application servers in a cluster, using the same database.

Here is a diagram illustrating the caching of statements in the database:

The caching of PreparedStatement's in the database.

The diagram does not show the JDBC driver PreparedStatement cache. You will have to imagine that.

Page 15: Introduction to JDBC and JDBC Drivers

Enterprise Java Jan-June 2014

Prepared by: Mr. Hitesh Kumar Sharma & Mr. Ravi Tomar Page 15 To be submitted by: B.Tech CS VI Sem (MFT+O&G+OSS+CCVT)

4. JDBC: CALLABLESTATEMENT

A java.sql.CallableStatement is used to call stored procedures in a database.

A stored procedure is like a function or method in a class, except it lives inside the database. Some database heavy operations may benefit performance-wise from being executed inside the same memory space as the database server, as a stored procedure.

4.1. Creating a CallableStatement

You create an instance of a CallableStatement by calling the prepareCall() method on a connection object. Here is an example:

CallableStatement callableStatement = connection.prepareCall("{call calculateStatistics(?, ?)}");

If the stored procedure returns a ResultSet, and you need a non-default ResultSet (e.g. with different holdability, concurrency etc. characteristics), you will need to specify these characteristics already when creating theCallableStatement. Here is an example:

CallableStatement callableStatement = connection.prepareCall("{call calculateStatistics(?, ?)}", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.CLOSE_CURSORS_OVER_COMMIT );

4.2. Setting Parameter Values

Once created, a CallableStatement is very similar to a PreparedStatement. For instance, you can set parameters into the SQL, at the places where you put a ? . Here is an example:

CallableStatement callableStatement = connection.prepareCall("{call calculateStatistics(?, ?)}"); callableStatement.setString(1, "param1"); callableStatement.setInt (2, 123);

Page 16: Introduction to JDBC and JDBC Drivers

Enterprise Java Jan-June 2014

Prepared by: Mr. Hitesh Kumar Sharma & Mr. Ravi Tomar Page 16 To be submitted by: B.Tech CS VI Sem (MFT+O&G+OSS+CCVT)

4.3. Executing the CallableStatement

Once you have set the parameter values you need to set, you are ready to execute the CallableStatement. Here is how that is done:

ResultSet result = callableStatement.executeQuery();

The executeQuery() method is used if the stored procedure returns a ResultSet.

If the stored procedure just updates the database, you can call the executeUpdate() method instead, like this:

callableStatement.executeUpdate();

OUT Parameters

A stored procedure may return OUT parameters. That is, values that are returned instead of, or in addition to, aResultSet. After executing the CallableStatement you can then access these OUT parameters from theCallableStatement object. Here is an example:

CallableStatement callableStatement = connection.prepareCall("{call calculateStatistics(?, ?)}"); callableStatement.setString(1, "param1"); callableStatement.setInt (2, 123); callableStatement.registerOutParameter(1, java.sql.Types.VARCHAR); callableStatement.registerOutParameter(2, java.sql.Types.INTEGER); ResultSet result = callableStatement.executeQuery(); while(result.next()) { ... } String out1 = callableStatement.getString(1); int out2 = callableStatement.getInt (2);

It is recommended that you first process the ResultSet before trying to access any OUT parameters. This is recommended for database compatibility reasons.

Page 17: Introduction to JDBC and JDBC Drivers

Enterprise Java Jan-June 2014

Prepared by: Mr. Hitesh Kumar Sharma & Mr. Ravi Tomar Page 17 To be submitted by: B.Tech CS VI Sem (MFT+O&G+OSS+CCVT)

5. BATCH UPDATES

A batch update is a batch of updates grouped together, and sent to the database in one "batch", rather than sending the updates one by one.

Sending a batch of updates to the database in one go, is faster than sending them one by one, waiting for each one to finish. There is less network traffic involved in sending one batch of updates (only 1 round trip), and the database might be able to execute some of the updates in parallel. The speed up compared to executing the updates one by one, can be quite big.

You can batch both SQL inserts, updates and deletes. It does not make sense to batch select statements.

There are two ways to execute batch updates:

1. Using a Statement

2. Using a PreparedStatement

This text explains both ways.

5.1. Statement Batch Updates

You can use a Statement object to execute batch updates. You do so using the addBatch() andexecuteBatch() methods. Here is an example:

Statement statement = null; try{ statement = connection.createStatement(); statement.addBatch("update people set firstname='John' where id=123"); statement.addBatch("update people set firstname='Eric' where id=456"); statement.addBatch("update people set firstname='May' where id=789"); int[] recordsAffected = statement.executeBatch(); } finally { if(statement != null) statement.close(); }

First you add the SQL statements to be executed in the batch, using the addBatch() method.

Then you execute the SQL statements using the executeBatch(). The int[] array returned by theexecuteBatch() method is an array of int telling how many records were affected by each executed SQL statement in the batch.

Page 18: Introduction to JDBC and JDBC Drivers

Enterprise Java Jan-June 2014

Prepared by: Mr. Hitesh Kumar Sharma & Mr. Ravi Tomar Page 18 To be submitted by: B.Tech CS VI Sem (MFT+O&G+OSS+CCVT)

5.2. PreparedStatement Batch Updates

You can also use a PreparedStatement object to execute batch updates. The PreparedStatement enables you to reuse the same SQL statement, and just insert new parameters into it, for each update to execute. Here is an example:

String sql = "update people set firstname=? , lastname=? where id=?"; PreparedStatement preparedStatement = null; try{ preparedStatement = connection.prepareStatement(sql); preparedStatement.setString(1, "Gary"); preparedStatement.setString(2, "Larson"); preparedStatement.setLong (3, 123); preparedStatement.addBatch(); preparedStatement.setString(1, "Stan"); preparedStatement.setString(2, "Lee"); preparedStatement.setLong (3, 456); preparedStatement.addBatch(); int[] affectedRecords = preparedStatement.executeBatch(); }finally { if(preparedStatement != null) { preparedStatement.close(); } }

First a PreparedStatement is created from an SQL statement with question marks in, to show where the parameter values are to be inserted into the SQL.

Second, each set of parameter values are inserted into the preparedStatement, and the addBatch() method is called. This adds the parameter values to the batch internally. You can now add another set of values, to be inserted into the SQL statement. Each set of parameters are inserted into the SQL and executed separately, once the full batch is sent to the database.

Third, the executeBatch() method is called, which executes all the batch updates. The SQL statement plus the parameter sets are sent to the database in one go. The int[] array returned by the executeBatch() method is an array of int telling how many records were affected by each executed SQL statement in the batch.

Page 19: Introduction to JDBC and JDBC Drivers

Enterprise Java Jan-June 2014

Prepared by: Mr. Hitesh Kumar Sharma & Mr. Ravi Tomar Page 19 To be submitted by: B.Tech CS VI Sem (MFT+O&G+OSS+CCVT)

5.3. Batch Updates and Transactions

It is important to keep in mind, that each update added to a Statement or PreparedStatement is executed separately by the database. That means, that some of them may succeed before one of them fails. All the statements that have succeeded are now applied to the database, but the rest of the updates may not be. This can result in an inconsistent data in the database.

To avoid this, you can execute the batch update inside a transaction. When executed inside a transaction you can make sure that either all updates are executed, or none are. Any successful updates can be rolled back, in case one of the updates fail.

Page 20: Introduction to JDBC and JDBC Drivers

Enterprise Java Jan-June 2014

Prepared by: Mr. Hitesh Kumar Sharma & Mr. Ravi Tomar Page 20 To be submitted by: B.Tech CS VI Sem (MFT+O&G+OSS+CCVT)

6. JDBC: TRANSACTIONS

A transaction is a set of actions to be carried out as a single, atomic action. Either all of the actions are carried out, or none of them are.

The classic example of when transactions are necessary is the example of bank accounts. You need to transfer $100 from one account to the other. You do so by subtracting $100 from the first account, and adding $100 to the second account. If this process fails after you have subtracted the $100 fromt the first bank account, the $100 are never added to the second bank account. The money is lost in cyber space.

To solve this problem the subtraction and addition of the $100 are grouped into a transaction. If the subtraction succeeds, but the addition fails, you can "rollback" the fist subtraction. That way the database is left in the same state as before the subtraction was executed.

You start a transaction by this invocation:

connection.setAutoCommit(false);

Now you can continue to perform database queries and updates. All these actions are part of the transaction.

If any action attempted within the transaction fails, you should rollback the transaction. This is done like this:

connection.rollback();

If all actions succeed, you should commit the transaction. Committing the transaction makes the actions permanent in the database. Once committed, there is no going back. Committing the transaction is done like this:

connection.commit();

Of course you need a bit of try-catch-finally around these actions. Here is a an example:

Connection connection = ... try{ connection.setAutoCommit(false); // create and execute statements etc.

Page 21: Introduction to JDBC and JDBC Drivers

Enterprise Java Jan-June 2014

Prepared by: Mr. Hitesh Kumar Sharma & Mr. Ravi Tomar Page 21 To be submitted by: B.Tech CS VI Sem (MFT+O&G+OSS+CCVT)

connection.commit();

} catch(Exception e) {

connection.rollback(); } finally { if(connection != null) { connection.close(); } }

Here is a full example:

Connection connection = ... try{ connection.setAutoCommit(false); Statement statement1 = null; try{ statement1 = connection.createStatement(); statement1.executeUpdate("update people set name='John' where id=123"); } finally { if(statement1 != null) { statement1.close(); } } Statement statement2 = null; try{ statement2 = connection.createStatement(); statement2.executeUpdate("update people set name='Gary' where id=456"); } finally { if(statement2 != null) { statement2.close(); } } connection.commit(); } catch(Exception e) { connection.rollback(); } finally { if(connection != null) { connection.close(); } }

Page 22: Introduction to JDBC and JDBC Drivers

Enterprise Java Jan-June 2014

Prepared by: Mr. Hitesh Kumar Sharma & Mr. Ravi Tomar Page 22 To be submitted by: B.Tech CS VI Sem (MFT+O&G+OSS+CCVT)

7. JDBC: RESULTSET

The text about queries I shows how the result of a query is returned as a java.sql.ResultSet. This ResultSet is then iterated to inspect the result.

7.1. A ResultSet Contains Records

A ResultSet consists of records. Each records contains a set of columns. Each record contains the same amount of columns, although not all columns may have a value. A column can have a null value. Here is an illustration of aResultSet:

ResultSet example - records with columns

This ResultSet has 3 different columns (Name, Age, Gender), and 3 records with different values for each column.

7.2. Creating a ResultSet

You create a ResultSet by executing a Statement or PreparedStatement, like this:

Statement statement = connection.createStatement(); ResultSet result = statement.executeQuery("select * from people");

Or like this:

String sql = "select * from people"; PreparedStatement statement = connection.prepareStatement(sql); ResultSet result = statement.executeQuery();

Page 23: Introduction to JDBC and JDBC Drivers

Enterprise Java Jan-June 2014

Prepared by: Mr. Hitesh Kumar Sharma & Mr. Ravi Tomar Page 23 To be submitted by: B.Tech CS VI Sem (MFT+O&G+OSS+CCVT)

7.3. ResultSet Type, Concurrency and Holdability

When you create a ResultSet there are three attributes you can set. These are:

1. Type

2. Concurrency

3. Holdability

You set these already when you create the Statement or PreparedStatement, like this:

Statement statement = connection.createStatement( ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.CLOSE_CURSORS_OVER_COMMIT ); PreparedStatement statement = connection.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.CLOSE_CURSORS_OVER_COMMIT );

Precisely what these attributes mean is explained later in this text. But now you now where to specify them.

7.4. Iterating the ResultSet

To iterate the ResultSet you use its next() method. The next() method returns true if the ResultSet has a next record, and moves the ResultSet to point to the next record. If there were no more records, next() returns false, and you can no longer. Once the next() method has returned false, you should not call it anymore. Doing so may result in an exception.

Here is an example of iterating a ResultSet using the next() method:

while(result.next()) { // ... get column values from this record }

As you can see, the next() method is actually called before the first record is accessed. That means, that theResultSet starts out pointing before the first record. Once next() has been called once, it points at the first record.

Page 24: Introduction to JDBC and JDBC Drivers

Enterprise Java Jan-June 2014

Prepared by: Mr. Hitesh Kumar Sharma & Mr. Ravi Tomar Page 24 To be submitted by: B.Tech CS VI Sem (MFT+O&G+OSS+CCVT)

Similarly, when next() is called and returns false, the ResultSet is actually pointing after the last record.

You cannot obtain the number of rows in a ResultSet except if you iterate all the way through it and count the rows. However, if the ResultSet is forward-only, you cannot afterwards move backwards through it. Even if you could move backwards, it would a slow way of counting the rows in the ResultSet. You are better off structuring your code so that you do not need to know the number of records ahead of time.

7.5. Accessing Column Values

When iterating the ResultSet you want to access the column values of each record. You do so by calling one or more of the many getXXX() methods. You pass the name of the column to get the value of, to the many getXXX()methods. For instance:

while(result.next()) { result.getString ("name"); result.getInt ("age"); result.getBigDecimal("coefficient"); // etc. }

There are a lot of getXXX() methods you can call, which return the value of the column as a certain data type, e.g. String, int, long, double, BigDecimal etc. They all take the name of the column to obtain the column value for, as parameter.

The getXXX() methods also come in versions that take a column index instead of a column name. For instance:

while(result.next()) { result.getString (1); result.getInt (2); result.getBigDecimal(3); // etc. }

The index of a column typically depends on the index of the column in the SQL statement. For instance, the SQL statement

select name, age, coefficient from person

Page 25: Introduction to JDBC and JDBC Drivers

Enterprise Java Jan-June 2014

Prepared by: Mr. Hitesh Kumar Sharma & Mr. Ravi Tomar Page 25 To be submitted by: B.Tech CS VI Sem (MFT+O&G+OSS+CCVT)

has three columns. The column name is listed first, and will thus have index 1 in the ResultSet. The column age will have index 2, and the column coefficient will have index 3. Sometimes you do not know the index of a certain column ahead of time. For instance, if you use a select * fromtype of SQL query, you do not know the sequence of the columns. If you do not know the index of a certain column you can find the index of that column using theResultSet.findColumn(String columnName) method, like this:

int nameIndex = result.findColumn("name"); int ageIndex = result.findColumn("age"); int coeffIndex = result.findColumn("coefficient"); while(result.next()) { String name = result.getString (nameIndex); int age = result.getInt (ageIndex); BigDecimal coefficient = result.getBigDecimal (coeffIndex); }

7.6. ResultSet Types

A ResultSet can be of a certain type. The type determines some characteristics and abilities of the ResultSet.

Not all types are supported by all databases and JDBC drivers. You will have to check your database and JDBC driver to see if it supports the type you want to use. The DatabaseMetaData.supportsResultSetType(int type)method returns true or false depending on whether the given type is supported or not. The DatabaseMetaDataclass is covered in a later text.

At the time of writing there are three ResultSet types:

1. ResultSet.TYPE_FORWARD_ONLY

2. ResultSet.TYPE_SCROLL_INSENSITIVE

3. ResultSet.TYPE_SCROLL_SENSITIVE

The default type is TYPE_FORWARD_ONLY

TYPE_FORWARD_ONLY means that the ResultSet can only be navigated forward. That is, you can only move from row 1, to row 2, to row 3 etc. You cannot move backwards in the ResultSet.

TYPE_SCROLL_INSENSITIVE means that the ResultSet can be navigated (scrolled) both forward and backwards. You can also jump to a position relative to the current position, or jump to an absolute position. The ResultSet is insensitive to changes in the underlying data source while

Page 26: Introduction to JDBC and JDBC Drivers

Enterprise Java Jan-June 2014

Prepared by: Mr. Hitesh Kumar Sharma & Mr. Ravi Tomar Page 26 To be submitted by: B.Tech CS VI Sem (MFT+O&G+OSS+CCVT)

the ResultSet is open. That is, if a record in theResultSet is changed in the database by another thread or process, it will not be reflected in already openedResulsSet's of this type.

TYPE_SCROLL_SENSITIVE means that the ResultSet can be navigated (scrolled) both forward and backwards. You can also jump to a position relative to the current position, or jump to an absolute position. The ResultSet is sensitive to changes in the underlying data source while the ResultSet is open. That is, if a record in theResultSet is changed in the database by another thread or process, it will be reflected in already openedResulsSet's of this type. 7.7. Navigation Methods

The ResultSet interface contains the following navigation methods. Remember, not all methods work with allResultSet types. What methods works depends on your database, JDBC driver, and the ResultSet type. Method Description

absolute() Moves the ResultSet to point at an absolute position. The position is a row number passed as parameter to the absolute() method.

afterLast() Moves the ResultSet to point after the last row in the ResultSet.

beforeFirst() Moves the ResultSet to point before the first row in the ResultSet.

first() Moves the ResultSet to point at the first row in the ResultSet.

last() Moves the ResultSet to point at the last row in the ResultSet.

next() Moves the ResultSet to point at the next row in the ResultSet.

previous() Moves the ResultSet to point at the previous row in the ResultSet.

relative() Moves the ResultSet to point to a position relative to its current position. The relative position is passed as a parameter to the relative method, and can be both positive and negative.

Moves the ResultSet

The ResultSet interface also contains a set of methods you can use to inquire about the current position of theResultSet. These are: Method Description

Page 27: Introduction to JDBC and JDBC Drivers

Enterprise Java Jan-June 2014

Prepared by: Mr. Hitesh Kumar Sharma & Mr. Ravi Tomar Page 27 To be submitted by: B.Tech CS VI Sem (MFT+O&G+OSS+CCVT)

getRow() Returns the row number of the current row - the row currently pointed to by the ResultSet.

getType() Returns the ResultSet type.

isAfterLast() Returns true if the ResultSet points after the last row. False if not.

isBeforeFirst() Returns true if the ResultSet points before the first row. False if not.

isFirst() Returns true if the ResultSet points at the first row. False if not.

Finally the ResultSet interface also contains a method to update a row with database changes, if the ResultSet is sensitive to change. Method Description

refreshRow() Refreshes the column values of that row with the latest values from the database.

7.8. ResultSet Concurrency

The ResultSet concurrency determines whether the ResultSet can be updated, or only read.

Some databases and JDBC drivers support that the ResultSet is updated, but not all databases and JDBC drivers do. The DatabaseMetaData.supportsResultSetConcurrency(int concurrency) method returns true or false depending on whether the given concurrency mode is supported or not. The DatabaseMetaData class is covered in a later text.

A ResultSet can have one of two concurrency levels:

1. ResultSet.CONCUR_READ_ONLY

2. ResultSet.CONCUR_UPDATABLE

CONCUR_READ_ONLY means that the ResultSet can only be read.

CONCUR_UPDATABLE means that the ResultSet can be both read and updated.

Page 28: Introduction to JDBC and JDBC Drivers

Enterprise Java Jan-June 2014

Prepared by: Mr. Hitesh Kumar Sharma & Mr. Ravi Tomar Page 28 To be submitted by: B.Tech CS VI Sem (MFT+O&G+OSS+CCVT)

7.9. Updating a ResultSet

If a ResultSet is updatable, you can update the columns of each row in the ResultSet. You do so using the manyupdateXXX() methods. For instance:

result.updateString ("name" , "Alex"); result.updateInt ("age" , 55); result.updateBigDecimal ("coefficient", new BigDecimal("0.1323"); result.updateRow();

You can also update a column using column index instead of column name. Here is an example:

result.updateString (1, "Alex"); result.updateInt (2, 55); result.updateBigDecimal (3, new BigDecimal("0.1323"); result.updateRow();

Notice the updateRow() call. It is when updateRow() is called that the database is updated with the values of the row. Id you do not call this method, the values updated in the ResultSet are never sent to the database. If you callupdateRow() inside a transaction, the data is not actually committed to the database until the transaction is committed.

7.10. Inserting Rows into a ResultSet

If the ResultSet is updatable it is also possible to insert rows into it. You do so by:

1. call ResultSet.moveToInsertRow()

2. update row column values

3. call ResultSet.insertRow()

Here is an example:

result.moveToInsertRow(); result.updateString (1, "Alex"); result.updateInt (2, 55); result.updateBigDecimal (3, new BigDecimal("0.1323"); result.insertRow(); result.beforeFirst();

The row pointed to after calling moveToInsertRow() is a special row, a buffer, which you can use to build up the row until all column values has been set on the row.

Page 29: Introduction to JDBC and JDBC Drivers

Enterprise Java Jan-June 2014

Prepared by: Mr. Hitesh Kumar Sharma & Mr. Ravi Tomar Page 29 To be submitted by: B.Tech CS VI Sem (MFT+O&G+OSS+CCVT)

Once the row is ready to be inserted into the ResultSet, call the insertRow() method.

After inserting the row the ResultSet still pointing to the insert row. However, you cannot be certain what will happen if you try to access it, once the row has been inserted. Therefore you should move the ResultSet to a valid position after inserting the new row. If you need to insert another row, explicitly call moveToInsertRow() to signal this to the ResultSet.

7.11. ResultSet Holdability

The ResultSet holdability determines if a ResultSet is closed when the commit() method of the underlyingconnection is called.

Not all holdability modes are supported by all databases and JDBC drivers. TheDatabaseMetaData.supportsResultSetHoldability(int holdability) returns true or false depending on whether the given holdability mode is supported or not. The DatabaseMetaData class is covered in a later text.

There are two types of holdability:

1. ResultSet.CLOSE_CURSORS_OVER_COMMIT

2. ResultSet.HOLD_CURSORS_OVER_COMMIT

The CLOSE_CURSORS_OVER_COMMIT holdability means that all ResultSet instances are closed whenconnection.commit() method is called on the connection that created the ResultSet.

The HOLD_CURSORS_OVER_COMMIT holdability means that the ResultSet is kept open when theconnection.commit() method is called on the connection that created the ResultSet.

The HOLD_CURSORS_OVER_COMMIT holdability might be useful if you use the ResultSet to update values in the database. Thus, you can open a ResultSet, update rows in it, call connection.commit() and still keep the sameResultSet open for future transactions on the same rows.

Page 30: Introduction to JDBC and JDBC Drivers

Enterprise Java Jan-June 2014

Prepared by: Mr. Hitesh Kumar Sharma & Mr. Ravi Tomar Page 30 To be submitted by: B.Tech CS VI Sem (MFT+O&G+OSS+CCVT)

8. TWO-TIER / THREE-TIER CLIENT-SERVER ARCHITECTURE

All projects are broadly divided into two types of applications 2 tier and 3 tier architecture. Basically high level we can say that 2-tier architecture is Client server application and 3-tier architecture is Web based application. Below I am concentrating on the difference between Two-Tier and Three-Tier Architecture, what all advantages, disadvantages and practical examples.

8.1.Two-Tier Architecture:

The two-tier is based on Client Server architecture. The two-tier architecture is like client server application. The direct communication takes place between client and server. There is no intermediate between client and server. Because of tight coupling a 2 tiered application will run faster.

Two-Tier Architecture

The above figure shows the architecture of two-tier. Here the direct communication between client and server, there is no intermediate between client and server. Let’s take a look of real life example of Railway Reservation two-tier architecture: Let’s consider that first Person is making Railway Reservation for Mumbai to Delhi by Mumbai Express at Counter No. 1 and at same time second Person is also try to make Railway reservation of Mumbai to Delhi from Counter No. 2 If staff from Counter No. 1 is searching for availability into system & at the same staff from Counter No. 2 is also looking for availability of ticket for same day then in this case there is might be good change of confusion and chaos occurs. There might be chance of lock the Railway reservation that reserves the first. But reservations can be making anywhere from the India, then how it is handled?

Page 31: Introduction to JDBC and JDBC Drivers

Enterprise Java Jan-June 2014

Prepared by: Mr. Hitesh Kumar Sharma & Mr. Ravi Tomar Page 31 To be submitted by: B.Tech CS VI Sem (MFT+O&G+OSS+CCVT)

So here if there is difference of micro seconds for making reservation by staff from Counter No. 1 & 2 then second request is added into queue. So in this case the Staff is entering data to Client Application and reservation request is sent to the database. The database sends back the information/data to the client.

In this application the Staff user is an end user who is using Railway reservation application software. He gives inputs to the application software and it sends requests to Server. So here both Database and Server are incorporated with each other, so this technology is called as “Client-Server Technology“.

The Two-tier architecture is divided into two parts:

1) Client Application (Client Tier) 2) Database (Data Tier)

On client application side the code is written for saving the data in the SQL server database. Client sends the request to server and it process the request & send back with data. The main problem of two tier architecture is the server cannot respond multiple request same time, as a result it cause a data integrity issue.

Advantages:

1. Easy to maintain and modification is bit easy 2. Communication is faster

Disadvantages:

1. In two tier architecture application performance will be degrade upon increasing the users.

2. Cost-ineffective

8.2. Three-Tier Architecture:

Three-tier architecture typically comprise a presentation tier, a business or data access tier, and a data tier. Three layers in the three tier architecture are as follows:

1) Client layer 2) Business layer 3) Data layer

1) Client layer: It is also called as Presentation layer which contains UI part of our application. This layer is used for the design purpose where data is presented to the user or input is taken from the user. For example designing registration form which contains text box, label, button etc.

Page 32: Introduction to JDBC and JDBC Drivers

Enterprise Java Jan-June 2014

Prepared by: Mr. Hitesh Kumar Sharma & Mr. Ravi Tomar Page 32 To be submitted by: B.Tech CS VI Sem (MFT+O&G+OSS+CCVT)

2) Business layer: In this layer all business logic written like validation of data, calculations, data insertion etc. This acts as a interface between Client layer and Data Access Layer. This layer is also called the intermediary layer helps to make communication faster between client and data layer.

3) Data layer: In this layer actual database is comes in the picture. Data Access Layer contains methods to connect with database and to perform insert, update, delete, get data from database based on our input data.

Three-tier Architecture

Advantages

1. High performance, lightweight persistent objects 2. Scalability – Each tier can scale horizontally 3. Performance – Because the Presentation tier can cache requests, network utilization is

minimized, and the load is reduced on the Application and Data tiers. 4. High degree of flexibility in deployment platform and configuration 5. Better Re-use 6. Improve Data Integrity 7. Improved Security – Client is not direct access to database. 8. Easy to maintain and modification is bit easy, won’t affect other modules 9. In three tier architecture application performance is good.

Disadvantages

1. Increase Complexity/Effort