1. 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
2. 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.
3. 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.
4. 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.
5. 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:
6. 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:
7. 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";
8. 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");
9. 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";
10. 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.
11. 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);
12. 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=?";
13. 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.
14. 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.
15. 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);
16. 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.
17. 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.
18. 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.
19. 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.
20. 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.
21. 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();
}
}
22. 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();
23. 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.
24. 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
25. 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
26. 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
27. 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.
28. 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.
29. 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.
30. 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?
31. 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.
32. 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