Chapter 21

1 downloads 0 Views 346KB Size Report
Java program and a database is a JDBC-ODBC driver. ..... int executeUpdate(String sql). Executes ..... public static void main(String[] args) throws Exception. { int ...
607

Chapter 21

JDBC In this chapter, programming concepts in Java to handle databases are explained. How to update, modify and execute SQL queries to a database are also discussed.

21.1 JDBC and ODBC The term JDBC is taken as an acronym for Java Database Connectivity, while Java developers state that it is not so. For a reader, JDBC may be taken to represent Java Database Connectivity. The Java Application Program Interface (API) makes a connection between Java application or applet and a database management system (DBMS or RDBMS). A DBMS has its own structure to organize its data. There are different types of DBMS developed by different vendors. Each DBMS has its own distinct structure. Any application written to access a DBMS of one vendor cannot be used to access the DBMS of another vendor. To solve this problem, Microsoft developed a standard called Open Database Connectivity (ODBC), which is free from any vendor-specific DBMS structure. A client using ODBC API can send SQL requests to a database server and get the results. A JDBC client does not make a direct link to a DBMS server. A JDBC makes use of ODBC to connect to DBMS servers. The bridge between a Java program and a database is a JDBC-ODBC driver. A conceptual structure of using a Java API in a client to handle a database in a server is shown in fig.21.1.

608

Programming in JAVA2

Client

Fig.21.1




JDBC Driver




Database Server

A Driver That Acts As An Interface Between a Client and Database Server

All DBMS or RDBMS need a driver if they are to be accessed from outside their own system. For example, a Java-Oracle driver is needed if Oracle database is to be accessed by a client running a Java application. Java has different types of drivers to access a DBMS.

21.1.1 Types of Drivers The drivers supporting Java language are classified into four types. They are classified based on the technique used to access a DBMS. All the models are supposed to work in a network. The same concept is applicable to a database available in a local machine also. Type I

:

JDBC-ODBC Bridge Driver

Type II

:

Native-API-Partly-Java Driver

Type III

:

JDBC-Net-All-Java Driver

Type IV

:

Native-Protocol-All-Java Driver

Type I : JDBC-ODBC Bridge Driver In this type, a JDBC-ODBC bridge acts as an interface between a client and a database server. An application in a client makes use of the JAVA API to send the requests to a database to the JDBC-ODBC bridge. The JDBCODBC bridge converts the JDBC API to ODBC API and sends it to the database server. The reply obtained from the database server is sent to the client via JDBC-ODBC driver. In this type, the JDBC-ODBC driver has to be installed in the client side. The Type I driver configuration is shown in fig.21.2.

JDBC

Client

609

Server

Client ¯

-

JDBC Driver -

¯

Database Server

ODBC Driver

¯ Network Interface

¯ Network Interface


Fig.21.2 Type I : The JDBC-ODBC Bridge Driver This driver is available in JDK 1.2. Type II : Native-API-Partly-Java Driver In this type of driver, the JDBC requests are translated to the Call Level Interface(CLI) of the database installed in the client machine to communicate with a database. When the database receives the requests, they are processed and sent back. This result in the native format of the database is converted to JDBC format and presented to the application running in a client. This type of driver offers a faster response than Type I drivers. The configuration of a Type II driver is shown in fig.21.3. Client

Server

Application ¯

-

JDBC Driver ¯

-

Native Database Libraries (CLI) ¯ Network Interface


610

Programming in JAVA2

Type III : JDBC-NET-ALL-Java Driver It is similar to Type II driver. and Native Database Libraries Communication between the client driver network protocol as shown in

The only difference is that JDBC for server (CLI) is stored in the remote server. and the server takes place using a JDBC fig.21.4. Server

Client

Database Server

Application

Native Database Libraries(CLI)

¯

-

-

JDBC Driver Client Side

¯ Network Interface

Network Interface

JDBC Driver Network Protocol

-

¯

¯

JDBC Driver Server Side

-

¯


Fig.21.4 Type III : JDBC-Net-All-Java Driver The advantage of this driver is that the client need not access any local disk to get the CLI. Hence, an applet can be used to access a database over a network. Type IV :

Native-Protocol-All-Java Driver

This type of a driver is 100% Java and does not make use of any CLI native libraries. In this type, no translation takes place. A JDBC makes a call directly to the database. It makes use of its own DB Protocol written in Java for network communication (fig.21.5). Client

Server

Application ¯

-

Database Server

JDBC Driver -

¯

Network Interface


JDBC

G

611

A java program needs a link called driver which can understand the JDBC requests and translate them to a format that can be understood by a database and vice versa.

21.1.2 Java SQL Package The classes required to handle a database are contained in a package java.sql. This package contains the following classes: Date DriverManager DriverPropertyInfo SQLPermission Time TimeStamp Types This package contains the following interfaces: Array CallableStatement Connection Driver PreparedStatement ResultSet Savepoint SQLInput Statement

Blob Clob DatabaseMetaData ParameterMetaData Ref ResultSetMetaData SQLData SQLOutput Struct

We will see the use and methods defined in some of them in the following sections.

21.2 Using a JDBC To use the JDBC in a Java language application or applet, the following steps are to be followed. They are: 1. 2. 3. 4. 5. 6. 7.

Import the java.sql package. Load the driver. Establish a connection to the database. Create a statement. Execute the statement. Retrieve the results. Close the connection and statement.

612

Programming in JAVA2

Step 1 :

Import sql package. The first step of importing java.sql is the routine procedure. import.java.sql.*;

Step 2 :

Load the driver. Loading of the driver is done using the following method: Class.forName(“sun.jdbc.odbc.JdbcOdbcDriver”); The driver specified is available in the JDK1.2.

Step 3 :

Establish connection. Connection is established with the database using the following method defined in the DriverManager class: Connection connect = DriverManager.getConnection(“jdbc:odbc: database”) where, “jdbc:odbc:database” is the database URL Object specifying the protocol, subprotocol and the database name.

Step 4 :

Prepare statement. In this step, statement object that is required to send a query to the database is prepared. This statement is prepared using the following method defined in Connection interface: Statement stmnt = conect.createStatement();

Step 5 :

Execute query The SQL query that is to be sent to the database is executed by calling the following method on statement object, which returns a ResultSet object: ResultSet reset = stmnt.executeQuery(“select * from database”);

Step 6 :

Retrieve the result. The results returned by the database to the query executed are extracted from ResultSet using the get method defined in ResultSet interface. while(reset.next()) System.out.println(“Name : “ + reset.getString(“name”);

Step 7 :

Close the statement and connection. Using the close method, the Statement and Connection are closed : conect.close(); stmnt.close();

The following program 21.1 illustrates the steps explained above. program retrieves an MS-Access database stored in a table “studata”.

This

JDBC

613

Program 21.1 /* This program demonstrates the creation of JDBC-ODBC connection and shows how to read a database created in MS-Access. [email protected] */ import java.sql.*; public class Sqlcon { public static void main(String args []) { Statement stm; ResultSet reset; try { // load the driver Class.forName(“sun.jdbc.odbc.JdbcOdbcDriver”); //establish connection Connection conect = DriverManager.getConnection(“jdbc: odbc:stud_base”); // create statment stm = conect.createStatement(); // execute the query and get the result reset = stm.executeQuery(“select * from studata “); System.out.println(“Name “ + “ \t” + “R.No” + “ \t” + “C.Org” + “\t” + “Java” + “ \t” + “Multimedia\n”); // retrieve the results while (reset.next()) System.out.println(reset.getString( “name”) + “\t” + reset.getInt(“rgno”) + “\t” + reset.getInt(“comporg”) + “\t” + reset.getInt(4) + “\t” + reset.getInt(5)); stm.close(); conect.close(); } catch (SQLException sqe) { System.out.println(“Sql error”); } catch (ClassNotFoundException cnf)

614

Programming in JAVA2 { System.out.println(“Class Not found error “); } } } The above program gives the following output: Name

R.No

Somasundaram K 1001 Magesh S 1002 Gomathi S 1003 Kumar S P 1004

C.Org Java

Multimedia

65 85 93 90

60 95 97 95

55 75 88 85

21.3 DriverManager - Creating Connection The DriverManager class contains methods to manage the JDBC drivers loaded in your program. The JDBC drivers are loaded using the forName() method. This class has no constructor, but has only static methods. Some of the methods defined in this class are: static Connection getConnection(String url) Creates a connection to the specified SQLException

database

URL;

throws

static Connection getConnection(String url, Properties prop) Creates a connection to the specified database URL using the properties specified; throws SQLException static Connection getConnection(String url, String user, String pswd) Creates a connection to the specified database URL using the user name and password; throws SQLException static Driver getDriver(String url) Selects a driver from the specified database url;

throws SQLException

The Connection objects are used to prepare statement objects, which are presented in the next section 2.4. JDBC URLs In the above methods, the url specified refers to database URLs. database URLs have three components. They are : 1. ProtocolName 2. Sub-protocol 3. Subname

The

JDBC

615

The syntax of JDBC URL is : : subname Protocol Name The protocol name specifies the protocol to access the database. It should be jdbc. Therefore all JDBC URLs have the form: jdbc : : Sub-protocol The sub-protocol is used to specify the type of database source, like Oracle, Sybase, etc. With the sub-protocol a JDBC URL may look like: jdbc : Oracle : < subname> Subname The subname specifies the database server. This name depends on the sub-protocol used. Each RDBMS has its own way of locating the source. The subname may be network host name, database listener port number/name or database instance name.

21.4 Connection Interface - Creating Statements The java.sql package contains an interface Connection. A Connection object represents an SQL session with database. This interface contains methods which can be used to prepare statements. These statements by themselves cannot be used, but provide a via medium to send SQL statements to the database. It also has methods to make the changes in the database permanent or roll back to a state before the last change. The important and very often used methods are those that prepare different statements. There are basically three types of statements. They are : Statement PreparedStatement CallableStatement Statement A Statement is used to execute static SQL statements. There are no IN or OUT parameters. When an SQL statement is executed, only one result is returned. PreparedStatement A PreparedStatement object is used to execute dynamic SQL statements with IN parameter. A PreparedStatement is compiled once by the database.

616

Programming in JAVA2

When SQL statements, which are large in size or are used repeatedly, a PreparedStatement can be used, which makes the process faster. CallableStatement A CallableStatement object is used for executing a stored procedure that can be used in an application. A CallableStatement contains an OUT parameter. It can also include IN parameter. The Connection interface has several concrete methods.

Some of them

are: void close() Releases the Connection object’s database and JDBC resources void commit() Makes all the changes made since the last commit or rollback permanent; throws SQLException Statement createStatement() Creates a Statement object for sending SQL statement to the database; throws SQLException boolean isClosed() Checks whether the connection is closed CallableStatement prepareCall(String sql) Creates a CallableStatement object for calling stored procedure; throws SQLException PreparedStatement prepareStatement(String sql) Creates a PreparedStatement object for sending SQL statement with or without IN parameter; throws SQLException void rollback() Undoes all changes made in the current transaction

G

Only by using methods in interface, Statement, PreparedStatement and CallableStatement objects are created.

21.5 Statement Interface - Executing Statements In the previous section, we have seen how to create different types of statements, Statement, PreparedStatement and CallableStatement. In this section, we will see how the Statement object created is used for executing static SQL statements. Statement is the simplest one to execute an SQL

JDBC

617

statement. The Statement interface has several concrete methods to execute SQL statements. Some of the methods defined in this interface are : void close() Releases the Statement object’s database and JDBC resources boolean execute(String sql) Executes the specified sql statement; the result obtained is to be retrieved using getResultSet() method ResultSet executeQuery(String sql) Executes the given sql statement and returns one ResultSet int executeUpdate(String sql) Executes the specified sql, which may be INSERT, DELETE or UPDATE int getMaxRows() Returns the maximum number of rows that the result set contains ResultSet getResultSet() Retrieves the ResultSet generated by the execute() method So far, we have seen how to create Connection object using DriverManager and Statement objects from Connection interface. In this section, we have seen how to execute Statement objects using methods defined in Statement interface. Now, we will give an example to illustrate the above concepts and to demonstrate some methods defined in Statement interface. The program 21.2 is almost the same as program 21.1, but with different methods to execute the SQL statement. In this program 21.2, we make use of a database created in MS-Access and stored in the table “studata”. It contains 5 fields, name, rgno, comporg, java and multimedia. There are four records (4 rows) in this database. We make the JDBC URL using this MS-Access database. For this, a database source is to be created. This is done using the following steps: 1.

Go to Control Panel

2.

Click Administrative Tools (Windows 2000)

618

Programming in JAVA2

Fig.21.6

Control Panel with Administrative Tool

3. Then Click Datasources (ODBC)

Fig.21.7

DataSource (ODBC)

4. Then You Will Get a Dialog Box Shown Below.

Select Add Button.

JDBC

Fig.21.8 5.

ODBC Dialog Box

From the Displayed Drivers Select Microsoft Access Driver (*.mdb) and press Finish.

Fig.21.9

Creating a New Data Source

619

620 6.

Programming in JAVA2 An ODBC Microsoft Access Setup Dialog Appears. In the Data Source Name, type a name of your choice (stu_base). A description can also be given. Then click select.

Fig.21.10 Assign a Data Source Name

7.

A Select Database Dialog Box Appears To Select the Physical Database. The table studata is stored in db3.mdb, in My Documents directory. Select db3 and press OK for all the remaining dialogs.

Fig.21.11

Select the Physical Database

To check whether the required jdbc data source has been created, go to the step 4, where the ODBC Data Source Administrator appears. The name “stu_base” is to be in the list.

JDBC

621

Program 21.2 /*

This program illustrates the use of the methods execute(String sql)and getResultSet() methods defined in the interface Connection. [email protected]

*/ import java.sql.*; public class Conect1 { public static void main(String args []) { Statement stm; ResultSet reset; try { // load the driver Class.forName(“sun.jdbc.odbc.JdbcOdbcDriver”); //establish connection Connection conect = DriverManager.getConnection(“jdbc: odbc:stu_base”); // create statment stm = conect.createStatement(); // execute the query and get the result stm.execute(“select * from studata “); // Retrieve the results reset = stm.getResultSet(); System.out.println(“Name“ + “ \t” + “R.No” + “ \t” + “C.Org” + “\t” + “Java” + “ \t” + “Multimedia\n”); // print the results while (reset.next()) System.out.println( reset.getString(“name”) + “\t” + reset.getInt(“rgno”) + “\t” + reset.getInt(“comporg”) + “\t” + reset.getInt(4) + “\t” + reset.getInt(5)); //close the statement and connection stm.close(); conect.close(); }

622

Programming in JAVA2 catch (SQLException sqe) { System.out.println(“Sql error”); } catch (ClassNotFoundException cnf) { System.out.println(“Class Not found error “); } } } The above program gives the following output: Name

R.No

Somasundaram K 1001 Magesh S 1002 Gomathi S 1003 Kumar S P 1004

C.Org Java

Multimedia

65 85 93 90

60 95 97 95

55 75 88 85

In the program 21.2, the driver is loaded using the forName() method. The driver sun.jdbc.odbc.JdbcOdbcDriver is available in the JDK1.2. To use other drivers, appropriate drivers are to be installed in the system. A Connection object is created by calling getConnection() method by passing the JDBC URL jdbc:odbc:stu_base. The string “Select * from studata” is the SQL statement, which selects all the records in studata table. A Statement object is created by calling the createStatement() on Connection object. The SQL statement is executed by calling execute() method on Statement object stm. This result created is retrieved using the getResultSet() method. This method returns a ResultSet object. The ResultSet may contain one or more rows of results. To get one row after another, the next() method is called. After obtaining a record(one row), the individual fields are then obtained using getString(“fieldname”) or getString(Column) method, which are defined in ResultSet interface. Comparing program 21.2 with program 21.1, you will notice that to execute a Statement, the execute() method is used in program 21.2. To get the result of the SQL statement, getResultSet() method is used. However, in program 21.1, the executeQuery() method, which is equivalent to the above two methods, is being used. In practice, executeQuery() method is more convenient to use than using the two methods. We now give an example in program 21.3 using executeUpdate() method. This program creates an MS-Access table named “pricelist”, containing

JDBC

623

two fields “item” of 20 char width and “price” of type Number. Three records are then inserted into it. The whole table is selected and printed out. The SQL statement used to insert each record is of the form : INSERT INTO pricelist (item, price) VALUES(‘NeemSoap’, 12.50) The string or char type values are placed in single quote. Program 21.3 /* This program illustrates the use of executeUpdate(String sql)method to create a new table named pricelist and inserts 3 records. The table is then printed out. [email protected] */ import java.sql.*; public class Insert { public static void main(String args []) { Statement stm; ResultSet reset; String sql, record1, record2, record3; try { // load the driver Class.forName(“sun.jdbc.odbc.JdbcOdbcDriver”); //establish connection Connection conect =DriverManager.getConnection (“jdbc:odbc:stu_base”); // prepare the SQL statement to create table // named pricelist stm = conect.createStatement(); sql = “create table pricelist (item char(20), price number)”; // execute the table creation sql stm.executeUpdate(sql); // create SQL statement for inserting records record1 = “insert into pricelist(item, price) values(‘Sandal soap’ , 18.75 )”; record2 = “insert into pricelist (item, price) values(‘Neem soap’ , 12.50 )”; record3 = “insert into pricelist (item, price) values(‘Baby soap’ , 20.00 )”; stm.executeUpdate(record1); stm.executeUpdate(record2);

624

Programming in JAVA2 stm.executeUpdate(record3); // make the changes permanent conect.commit(); // prepare SQL to select all records in // pricelist table String select = “select * from pricelist”; reset = stm.executeQuery(select); System.out.println(“Item “ + “ \t\t” + “Price\n”); // print the table while (reset.next()) System.out.println(reset.getString(“item”) + “\t” + reset.getDouble(“price”)); //close the statement and connection stm.close(); conect.close(); } catch (SQLException sqe) { System.out.println(“Sql error”); } catch (ClassNotFoundException cnf) { System.out.println(“Class Not found error “); } } } The above program gives the following output: Item

Price

Sandal soap Neem soap Baby soap

18.75 12.5 20.0

In the following program 21.4, we show how to use the SQL statement, which links two tables of MS-Access and extracts the required fields from them. The two tables used are “studata” with fields, name, rgno, comporg, java, multimedia and “pricelist” with fields, item and price. The SQL statement used is:

JDBC

625

SELECT name, item FROM studata, pricelist WHERE rgno = 1002 AND item = ‘Sandal Soap’ The executeQuery method is used to execute the SQL statement. The commit() method makes the insertions made permanent. rollback() when called after this is of no use unless new transactions are made. Program 21.4 /* This program illustrates how to link two tables and extract data from them which satisfy a given condition. [email protected] */ import java.sql.*; public class Select { public static void main(String args []) { Statement stm; ResultSet reset; String sql; try { // load the driver Class.forName(“sun.jdbc.odbc.JdbcOdbcDriver”); //establish connection Connection conect =DriverManager.getConnection (“jdbc:odbc:stu_base”); // prepare the SQL statement to select name // and item stm = conect.createStatement(); sql = “select name,item from studata, pricelist where rgno =1002 AND item = ‘Sandal soap’ “; reset = stm.executeQuery(sql); System.out.println(“Name “ + “ \t” + “Soap Used\n”); // print the result while (reset.next()) System.out.println(reset.getString(“name”) + “\t” + reset.getString(“item”));

626

Programming in JAVA2 //close the statement and connection stm.close(); conect.close(); } catch (SQLException sqe) { System.out.println(“Sql error”); } catch (ClassNotFoundException cnf) { System.out.println(“Class Not found error “); } } } The above program gives the following output:

G

Name

Soap Used

Magesh S

Sandal Soap

In Statement interface, the SQL statements are executed by passing the SQL statements as arguments to execute(), executeQuery() and executeUpdate() methods. The executeQuery() method returns the results of the query in ResultSet object.

21.6 PreparedStatement Interface A PreparedStatement object can be used to execute a dynamic SQL statement with IN parameter. A PreparedStatement can be precompiled and used repeatedly. This interface contains methods to handle PreparedStatement objects. The PreparedStatement object is created using prepareStatement() method in Connection class. Before we look into the methods, we will see how to define IN parameters in the Java SQL statements. Setting IN Parameters An IN parameter is used to execute a dynamic SQL statement. In situations, where the actual value of a parameter is to be passed to an SQL statement are different for each transaction, then such values can be specified by placing a “?” in the SQL statement. The actual value can be passed using the setXXX() method at the time of execution. The “?” in a Java SQL statement standing for an input parameter to be supplied after using setXXX() method. For example, the following statements show how an IN parameter is defined.

JDBC

627

String sql = “select * from studata where rgno > ?”; PreparedStatement pstm = conect.prepareStatement(sql); pstm.setInt(1,1002); ResultSet rst = pstm.executeQuery(); In the first line an SQL statement is defined. The ? mark stands for an IN parameter. In the second line, the PreparedStatement object is created. In the third one, we define that the IN parameter is an integer, which is the first IN parameter in the PreparedStatement. The general form of setting an IN parameter is: setXXX(int index, type value); where xxx - is the value type, index - is the position of IN parameter in the SQL statement, value - is the value to be supplied in place of ? We will now see some of the methods defined in PreparedStatement interface. All the methods throw SQLException. boolean execute() Executes the SQL statement in this object; one must use getResult() method to retrieve the result ResultSet executeQuery() Executes the SQL statement in this object and returns ResultSet object int executeUpdate() Executes the SQL statement in this object; an SQL insert, update and delete statement

the SQL statements must be

ResultSetMetaData getMetaData() Retrieves a ResultSetMetaData object that contains information about the columns of the ResultSet object that will be returned when this object is executed void setBigDecimal(int index, BigDecimal x) Sets the parameter specified by the index to the BigDecimal value void setBlob(int index, Blob x) Sets the specified parameter to the given Blob object void setBoolean(int index, boolean x) Sets the specified parameter to the boolean value void setByte(int index, byte x) Sets the specified parameter to the byte value

628

Programming in JAVA2

void setClob(int index, Clob x) Sets the specified parameter to the Clob object void setDate(int index, Date x) Sets the specified parameter to the Date value void setDouble(int index, double x) Sets the specified parameter to the double value void setFloat(int index, float x) Sets the specified parameter to the float value void setInt(int index, int x) Sets the specified parameter to the int value void setLong(int index, long x) Sets the specified parameter to the long value void setObject(int index, Object x) Sets the specified parameter to the Object void setShort(int index short x) Sets the specified parameter to the short value void setString(int index String x) Sets the specified parameter to the String value In the following program 21.5, we show how the IN parameter is used in a PreparedStatement. The program makes use of an MS-Access table “studata”, with fields, name, rgno, comporg, java, and multimedia. The SQL statement used is: SELECT * FROM studata WHERE comporg > ? AND java > ? and is defined in the sql string as : sql = “select * from studata where comporg > ? and java > ?”; The two ? marks stand for two IN parameter values. The IN parameters are both integers which are set using the following Java statements: pstm.setInt(1, 80); pstm.setInt(2,90); The first statement sets the first IN parameter to the value 80. second statement sets the second IN parameter to the value 90.

The The

JDBC

629

executeQuery() method executes the PreparedStatement object. The SQL statement is passed as an argument to the method prepareStatement() itself unlike statement object where the SQL statement is passed as an argument to the executeQuery() method. Program 21.5 /* This program illustrates the use of PreparedStatement() method. [email protected] */ import java.sql.*; public class Prepare1 { public static void main(String args []) { PreparedStatement pstm; ResultSet reset; String sql; try { // load the driver Class.forName(“sun.jdbc.odbc.JdbcOdbcDriver”); //establish connection Connection conect = DriverManager.getConnection(“jdbc: odbc:stu_base”); // define the SQL statement to create a // PreparedStatement sql = “select * from studata where comporg > ? and java > ? “; // create the PreparedStatement pstm = conect.prepareStatement(sql); // set the IN parameters pstm.setInt(1, 80); pstm.setInt(2, 90); // execute the PreparedStatement and get the // results reset = pstm.executeQuery(); // print the results System.out.println(“Name “ + “ \t” + “R.No” + “ \t” + “C.Org” + “\t” + “Java” + “ \t” + “Multimedia\n”);

630

Programming in JAVA2 while (reset.next()) System.out.println( reset.getString(“name”) + “\t” + reset.getInt(“rgno”) + “\t” + reset.getInt(“comporg”) + “\t” + reset.getInt(“java”) + “\t” + reset.getInt(“multimedia”)); //close the statement and connection pstm.close(); conect.close(); } catch (SQLException sqe) { System.out.println(“Sql error”); } catch (ClassNotFoundException cnf) { System.out.println(“Class Not found error “); } } } The above program gives the following output: Name

R.No

C.Org Java

Multimedia

Gomathi S Kumar S P

1003 1004

93 90

97 95

93 93

21.7 CallableStatement Interface A CallableStatement object is used to execute SQL stored procedures defined in the RDBMS. A procedure with OUT parameter can be executed only in this CallableStatement. A CallableStatement can also contain IN parameter. An OUT parameter has to be registered prior to executing the stored procedure. An OUT parameter in the stored procedure is represented by the ?. An OUT parameter is registered using the registerOutParameter() method. This method declares the type of the OUT parameter. After the CallableStatement is executed, the OUT parameters are to be obtained using the getXXX() method. The general form of registering OUT parameters other than NUMERIC and DECIMAL is: registerOutParamet( int index, Type type) where index - is the relative position of OUT parameter in the SQL statement type - is the SQL data type of OUT parameter.

JDBC

631

The following example illustrates the use of CallableStatement and registering OUT parameter. CallableStatement cstm = conect.prepareCall(EXECUTE PAY_ROLL (?, ?, ?)); There are 3 parameters. Let us say, the first two are IN parameter and the third is an OUT parameter. The IN and OUT parameters are defined in the following way: cstm.setString(1, “Raman”); cstm.setInt(2, 5000); cstm.registerOutParameter(3, Types.LONGVARCHAR); The CallableStatement is executed by calling the execute methods. ResultSet rst = cstm.executeQuery(); The registered OUT parameter can be retrieved using getxxx() method in CallableStatement interface. An example is : String outstr =

cstm.getString(3);

The CallableStatement interface has several methods inherited from Statement and PreparedStatement interfaces and some of its own. Some of them are : BigDecimal getBigDecimal(int index) Retrieves the OUT parameter of JDBC NUMERIC type at the specified index as BigDecimal object byte getByte(int index) Retrieves the OUT parameter of JDBC NUMERIC type at the specified index location as a byte Date getDate(int index) Retrieves the OUT parameter of JDBC DATE type at the specified index location as a Date double getDouble(int index) Retrieves the OUT parameter of type JDBC DOUBLE at the specified index location as a double float getFloat(int index) Retrieves the OUT parameter of type JDBC FLOAT at the specified index location as a float

632

Programming in JAVA2

int getInt(int index) Retrieves the OUT parameter of type JDBC INTEGER at the specified index location as an int long getLong(int index) Retrieves the OUT parameter of type JDBC LONG at the specified index location as an int String getString(int index) Retrieves the OUT parameter of type JDBC CHAR, VARCHAR or LONGVARCHAR at the specified index location as a String The following program 21.6 illustrates the use of CallableStatement: Program 21.6 /* This program illustrates the use of CallableStatement() method. [email protected] */ import java.sql.*; import java.io.*; public class ppro { public static void main(String[] args) throws Exception { int in_sregno; int ret_code ; Connection conn = null; try { Class.forName(“sun.jdbc.odbc.JdbcOdbcDriver”); String url=”jdbc:odbc:stu”; conn=DriverManager.getConnection(url, ”scott”,”tiger”); in_sregno = 1111; CallableStatement pstmt = conn.prepareCall(“{call pdisp(?,?,?,?)}”); pstmt.setInt(1, in_sregno); pstmt.registerOutParameter(2, Types.VARCHAR); pstmt.registerOutParameter(3, Types.INTEGER); pstmt.registerOutParameter(4, Types.INTEGER); pstmt.executeUpdate(); String o_sname = pstmt.getString(2); int o_m1 = pstmt.getInt(3); int o_m2 = pstmt.getInt(4); System.out.println(“”); System.out.println(“The output of this program is “);

JDBC

633

System.out.println(“”); System.out.println(“======”+”\t” +”==== “ + “\t\t” + “=====” +”\t” +”=====”); System.out.println(“sregno”+”\t” +”name “ +”\t\t” + “mark1” +”\t” +”mark2"); System.out.println(“======”+”\t” +”==== “ + “\t\t” + “=====” +”\t” +”=====”); System.out.println(in_sregno+”\t” +o_sname +”\t” + o_m1+”\t” +o_m2); pstmt.close(); conn.close(); } catch (SQLException e) { ret_code = e.getErrorCode(); System.err.println(ret_code + e.getMessage()); conn.close(); } } } The above program gives the following output: The output of this program is ====== sregno ====== 1111

==== name ==== Arumugam

===== ===== mark1 mark2 ===== ===== 90 80

The above program 21.6, makes a call to the following SQL program 21.7 stored in the Oracle database named “pdisp”. Program 21.7 The following SQL procedure is called in the above program 21.6: CREATE OR REPLACE PROCEDURE pdisp( in_sregno NUMBER, out_sname OUT varchar2, out_m1 OUT number, out_m2 OUT number ) is temp_sregno number; temp_sname VARCHAR2(10); temp_m1 NUMBER; temp_m2 number;

634

Programming in JAVA2 BEGIN SELECT sregno, sname,m1,m2 INTO temp_sregno, temp_sname, temp_m1, temp_m2 FROM mark WHERE sregno=in_sregno; out_sname := temp_sname; out_m1 := temp_m1; out_m2 := temp_m2; END;

G

CallableStatement is the only object that can execute a stored procedure with OUT parameter. A stored procedure is passed as an argument to the prepareCall() method. The executeQuery() and execucte() methods do not take any argument.

21.8 ResultSet Interface The executeQuery() and getResultSet() methods when called on Statement, PreparedStatement and Callablestatement return objects of type ResultSet. The ResultSet objects contain results after the execution of SQL statements. The ResultSet object maintains a cursor pointing to the current row of results. The next() method moves cursor to the next row of result set. The ResultSet interface has many methods to get the results from the result set. Some of them are given below: boolean absolute(int row) Moves the cursor to the specified row number in this result set void afterLast() Moves the cursor to the end of the result set just after the last row void close() Releases the object’s database void deleteRow() Deletes the current row of this result set boolean first() Moves the cursor to the first row BigDecimal getBigDecimal(int columnIndex) Retrieves the value of the specified column as BigDecimal

JDBC

boolean getBoolean(int columnIndex) Retrieves the value of the specified column as boolean boolean getBoolean(String columnName) Retrieves the value of the specified column name as boolean byte getByte(int columnIndex) Retrieves the value of the specified column as a byte byte getByte(String columnName) Retrieves the values of the specified column name as a byte Date getDate(int columnIndex) Retrieves the value of the specified column as a Date Date getDate(String columnName) Retrieves the value of the specified column name as a Date double getDouble(int columnIndex) Retrieves the value of the specified column as a double double getDouble(String columnName) Retrieves the value of the specified column name as a double float getFloat(int columnIndex) Retrieves the value of the specified column as a float float getFloat(String columnName) Retrieves the value of the specified column name as a float int getInt(int columnIndex) Retrieves the values of the specified column as an int int getInt(String columnName) Retrieves the values of the specified column name as an int long getLong(int columnIndex) Retrieves the values of the specified column as a long long getLong(String columnName) Retrieves the value of the specified column name as a long ResultSetMetaData getMetaData() Returns the properties of the ResultSet object int getRow() Returns the current row number

635

636

Programming in JAVA2

Statement getStatement() Returns the statement object which produced the ResultSet String getString(int columnIndex) Retrieves the value of the specified column as a String String getString(String columnName) Retrieves the value of the specified column name as String boolean isFirst() Checks whether the cursor is in first row boolean isLast() Checks whether the cursor is in the last row boolean last() Moves the cursor to the last row boolean next() Moves the cursor to the next row boolean previous() Moves the cursor to the previous row

After reading this chapter, you should have learned the following concepts: Ü

JDBC-ODBC Driver

Ü

Creating database tables

Ü

Executing SQL statements using: Statement, PreparedStatement and CallableStatement.

In the next chapter you will learn about Servlets used in JAVAEE5(J2EE).

JDBC

637

Worked Out Problems-21 Problem 21.1w A payroll database contains two tables. One table contains the permanent details of all employees with the following fields: Name Employee code Designation Basic pay

-

Character Number Character Number

Another table contains monthly transactions with the details: Medical allowance Transport allowance Income tax Provident fund Housing loan

-

Number Number Number Number Number

In addition to basic pay, an employee will be paid DA and House Rent Allowance (HRA) at the following rates: DA = HRA =

53% of Basic bay 10% of basic pay

The total salary of an employee is calculated as follows: Total pay

=

Basic pay + HRA + DA + Medical allowance + Transport allowance

Deduction

=

Income tax + Provident fund + Housing loan

Net Pay

=

Total pay - Deduction

Write a Java program to make monthly transactions and slip for each employee and display it on the screen.

prepare a pay

638

Programming in JAVA2

Program 21.1w /* This program illustrates how to make a payroll system for a company. It has two tables, master and month-transaction. This program has the following modules: 1. A module to enter monthly details 2. A module for preparing the payslips [email protected] */ import import import import import

java.awt.*; java.awt.event.*; javax.swing.*; java.util.*; java.sql.*;

class Monthpanel extends JPanel implements ActionListener { JTextField namef, codef, transportf, medicalf, pff, loanf, itf; JLabel namel, codel, transportl, medicall, pfl, loanl, itl; boolean more; // The following are values to be obtained from the // database table employee_month String empname; int empcode; int transport, medical, pf, loan, it; JButton cal, clear; // date variables int day, month, year; String date; JLabel datel, datefield; Monthpanel(NextRecord obj) { // creating current date GregorianCalendar calendr = new GregorianCalendar(); day = calendr.get(Calendar.DATE); month = calendr.get(Calendar.MONTH); month += 1; // January is 0 hence this conversion year = calendr.get(Calendar.YEAR); date = “ “ + day + “-” + month + “-” + year;

JDBC

setLayout(new GridLayout(11, 2)); empcode = 0; transport = 0; medical = 0; pf = 0; loan = 0; it = 0; empname = obj.empname; empcode = obj.empcode; transport = obj.transport; medical = obj.medical; pf = obj.pf; loan = obj.loan; it = obj.it; JLabel maintitle = new JLabel(“ PAYROLL”); JLabel monthtitle = new JLabel(“ - MONTHLY DETAIL ENTRY “); datel = new JLabel(“Date “); datefield = new JLabel(date); namel = new JLabel(“Name”); namef = new JTextField(empname); namef.setEditable(false); codel = new JLabel(“Employee Code “); codef = new JTextField(“” + empcode); transportl = new JLabel(“Tranport “); transportf = new JTextField(“” + transport); medicall = new JLabel(“Medical”); medicalf = new JTextField(“” + medical); pfl = new JLabel(“Provident Fund “); pff = new JTextField(“” + pf); loanl = new JLabel(“Loan “); loanf = new JTextField(“” + loan); itl = new JLabel(“Income Tax “); itf = new JTextField(“” + it); JButton clr = new JButton(“CLEAR ENTRY”); clr.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { transportf.setText(“” + 0); medicalf.setText(“” + 0); pff.setText(“” + 0); loanf.setText(“” + 0); itf.setText(“” + 0); } }); JButton upd = new JButton(“UPDATE RECORD”);

639

640

Programming in JAVA2 add(maintitle); add(monthtitle); add(datel); add(datefield); add(namel); add(namef); add(codel); add(codef); add(transportl); add(transportf); add(medicall); add(medicalf); add(pfl); add(pff); add(loanl); add(loanf); add(itl); add(itf); add(clr); add(upd); upd.addActionListener(this); JButton ext = new JButton(“EXIT”); add(ext); ext.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { System.exit(0); } }); } public void actionPerformed(ActionEvent ae) { // get the updated values String empnam = namef.getText(); int empcod = Integer.parseInt(codef.getText()); int trans = Integer.parseInt(transportf.getText()); int medi = Integer.parseInt(medicalf.getText()); int pfamt = Integer.parseInt(pff.getText()); int lon = Integer.parseInt(loanf.getText()); int intax = Integer.parseInt(itf.getText()); //update the records in the database try { //Register the JDBCODBC driver Class.forName(“sun.jdbc.odbc.JdbcOdbcDriver”);

JDBC

641

Connection conect = DriverManager.getConnection(“jdbc: odbc:stu_base”); String sql=“update employe_month set transport =?, medical = ?, pf=?,loan=?,it=? where emp_code=?”; PreparedStatement pstm = conect.prepareStatement(sql); pstm.setInt(1, trans); pstm.setInt(2, medi); pstm.setInt(3, pfamt); pstm.setInt(4, lon); pstm.setInt(5, intax); pstm.setInt(6, empcod); pstm.executeUpdate(); conect.commit(); } catch (SQLException sqe) { System.out.println(“Sql error in update “); } catch (ClassNotFoundException cnf) { System.out.println(“Class Not found error “); } } } class NextRecord { String empname; int empcode; int transport, medical, pf, loan, it; ResultSet rst; NextRecord(ResultSet rset) { try { rst = rset; empname = rst.getString(1); empcode = rst.getInt(2); transport = rst.getInt(3); medical = rst.getInt(4); pf = rst.getInt(5); loan = rset.getInt(6); it = rst.getInt(7); } catch (SQLException sqe) {

642

Programming in JAVA2 System.out.println(“Sql error in NextRecord”); } } } class Editframe extends JFrame { Container conpan; Statement stm; ResultSet reset; boolean processed = false; NextRecord nxtrec; Connection conect; Editframe(String str) { super(str); conpan = getContentPane(); setSize(340, 350); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); JButton nxt = new JButton(“NEXT RECORD”); conpan.setLayout(new BorderLayout()); try { //Register the JDBCODBC driver Class.forName(“sun.jdbc.odbc.JdbcOdbcDriver”); conect = DriverManager.getConnection(“jdbc: odbc:stu_base”); stm = conect.createStatement(); // select all records from employee_month table reset = stm.executeQuery(“select * from employe_month “); while (reset.next()) { nxtrec = new NextRecord(reset);

conpan.add(new Monthpanel(nxtrec), BorderLayout.NORTH); conpan.add(nxt, BorderLayout.SOUTH); setVisible(true);

JDBC

643

while (!processed) { nxt.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { processed = true; } }); } processed = false; } // while end } catch (SQLException sqe) { System.out.println(“Sql error in EditFRame class”); } catch (ClassNotFoundException cnf) { System.out.println(“Class Not found error “); } } } class Paypanel extends JPanel { JTextField namef, codef, designf, bpayf, totalf, deductionf, netpayf, transportf, medicalf, pff, loanf, itf; JTextField hraf, daf; JLabel payl1, payl2, dedl1, dedl2, dal, hral; JLabel namel, codel, designl, bpayl, totall, deductionl, netpayl, transportl, medicall, pfl, loanl, itl; // The following are values to be obtained from the // database table employee_month String empname, design; int empcode; int transport, medical, pf, loan, it; int bpay, hra, da, deduction, totalpay, netpay; // date variables int day, month, year; String date; JLabel datel, datefield;

644

Programming in JAVA2 Paypanel(Payrec obj) { // creating current date GregorianCalendar calendr = new GregorianCalendar(); day = calendr.get(Calendar.DATE); month = calendr.get(Calendar.MONTH); month += 1; // January is 0 hence this conversion year = calendr.get(Calendar.YEAR); date = “ “ + day + “-” + month + “-” + year; setLayout(new GridLayout(19, 2)); empname = obj.ename; empcode = obj.ecode; design = obj.design; bpay = obj.bpay; transport = obj.trans; medical = obj.medi; pf = obj.pfam; loan = obj.loanam; it = obj.itam; totalpay = obj.totalpay; netpay = obj.netpay; hra = obj.hra; da = obj.da; deduction = obj.deduction; JLabel maintitle = new JLabel(“ PAYROLL”); JLabel monthtitle = new JLabel(“ -PAYSLIP “); datel = new JLabel(“Date “); datefield = new JLabel(date); payl1 = new JLabel(“ PAY DETAILS”); payl2 = new JLabel(“ Rs. “); namel = new JLabel(“Name”); namef = new JTextField(empname); namef.setEditable(false); codel = new JLabel(“Employee Code “); codef = new JTextField(“” + empcode); codef.setEditable(false); designl = new JLabel(“Designation”); designf = new JTextField(design); designf.setEditable(false); bpayl = new JLabel(“Basic Pay”); bpayf = new JTextField(“” + bpay); bpayf.setEditable(false); hral = new JLabel(“House Rent “); hraf = new JTextField(“” + hra); hraf.setEditable(false); dal = new JLabel(“Dearness Allowance”); daf = new JTextField(“” + da); daf.setEditable(false); transportl = new JLabel(“Transport “);

JDBC

transportf = new JTextField(“” + transport); transportf.setEditable(false); medicall = new JLabel(“Medical”); medicalf = new JTextField(“” + medical); medicalf.setEditable(false); totall = new JLabel(“Total Pay”); totalf = new JTextField(“” + totalpay); totalf.setEditable(false); dedl1 = new JLabel(“DEDUCTIONS”); dedl2 = new JLabel(“ Rs.”); pfl = new JLabel(“Provident Fund “); pff = new JTextField(“” + pf); pff.setEditable(false); loanl = new JLabel(“Loan “); loanf = new JTextField(“” + loan); loanf.setEditable(false); itl = new JLabel(“Income Tax “); itf = new JTextField(“” + it); itf.setEditable(false); deductionl = new JLabel(“Total Deduction”); deductionf = new JTextField(“” + deduction); deductionf.setEditable(false); netpayl = new JLabel(“Net Pay”); netpayf = new JTextField(“” + netpay); netpayf.setEditable(false); add(maintitle); add(monthtitle); add(datel); add(datefield); add(payl1); add(payl2); add(namel); add(namef); add(codel); add(codef); add(designl); add(designf); add(bpayl); add(bpayf); add(hral); add(hraf); add(dal); add(daf); add(transportl); add(transportf); add(medicall); add(medicalf); add(totall); add(totalf);

645

646

Programming in JAVA2 add(dedl1); add(dedl2); add(pfl); add(pff); add(loanl); add(loanf); add(itl); add(itf); add(deductionl); add(deductionf); add(netpayl); add(netpayf); JButton ext = new JButton(“EXIT”); add(ext); ext.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { System.exit(0); } }); } } class Payrec { String ename, design; int ecode, bpay, trans, medi, pfam, loanam, itam; int hra, da; int totalpay, deduction, netpay; Payrec(ResultSet pobj) { try { ename = pobj.getString(1); ecode = pobj.getInt(2); design = pobj.getString(3); bpay = pobj.getInt(4); trans = pobj.getInt(5); medi = pobj.getInt(6); pfam = pobj.getInt(7); loanam = pobj.getInt(8); itam = pobj.getInt(9); hra = (int)(bpay * 0.10); da = (int)(bpay * 0.53); totalpay = bpay + hra + da + trans + medi; deduction = pfam + loanam + itam; netpay = totalpay - deduction; } catch (SQLException sqe)

JDBC

647

{ System.out.println(“Sql error in NextRecord”); } } } class Payframe extends JFrame { Container conpan; Statement stm; ResultSet reset; boolean processed = false; Payrec rec; Connection conect; Payframe(String str) { super(str); conpan = getContentPane(); setSize(340, 600); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); JButton nxt = new JButton(“NEXT PERSON”); conpan.setLayout(new BorderLayout()); try { //Register the JDBCODBC driver Class.forName(“sun.jdbc.odbc.JdbcOdbcDriver”); conect = DriverManager.getConnection(“jdbc: odbc:stu_base”); stm = conect.createStatement(); // select allrecords from employee_month and //employee_master tables reset = stm.executeQuery(“select ems.emp_name, ems.emp_code, ems.design, ems.basic_pay, em.transport, em.medical, em.pf,em.loan, em.it from employee_master ems,employe_month em where ems.emp_code= em.emp_code “);

648

Programming in JAVA2 while (reset.next()) { rec = new Payrec(reset); conpan.add(new Paypanel(rec), BorderLayout.NORTH); conpan.add(nxt, BorderLayout.SOUTH); setVisible(true); while (!processed) { nxt.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { processed = true; } }); } processed = false; } // while end } catch (SQLException sqe) { System.out.println(“Sql error in Payframe class”); } catch (ClassNotFoundException cnf) { System.out.println(“Class Not found error “); } } } // Thread class class Editthread implements Runnable { String title; Thread th; Editthread(String str) { title = str; th = new Thread(this, “editthread”); th.start();

JDBC

649

} public void run() { new Editframe(title); } } class Paythread implements Runnable { String title; Thread th; Paythread(String str) { title = str; th = new Thread(this, “Paythread”); th.start(); } public void run() { new Payframe(title); } } class Mainmenu extends JFrame { Container conpan; JPanel mp; Mainmenu(String str) { super(str); conpan = getContentPane(); conpan.setLayout(new GridLayout(3, 2)); setSize(300, 150); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); JLabel editl = new JLabel(“Edit the monthly detail”); JButton edit = new JButton(“EDIT RECORDS”);

650

Programming in JAVA2 JLabel payl = new JLabel(“Prepare payslips “); JButton pay = new JButton(“DISPLAY PAYSLIPS”); JLabel extl = new JLabel(“Exit the payroll system”); JButton exit = new JButton(“EXIT”); conpan.add(editl); conpan.add(edit); edit.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { new Editthread(“EDIT RECORDS”); } }); conpan.add(payl); conpan.add(pay); pay.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { new Paythread(“PAYSLIP PREPARATION “); } }); conpan.add(extl); conpan.add(exit); exit.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { System.exit(0); } }); setVisible(true); } } class Probtest { public static void main(String args []) { new Mainmenu(“PAYROLL PREPARATION “); } }

JDBC

The above program gives the following output:

(a)

(b)

651

652

Programming in JAVA2

Fig.21.12

(c) Output Screens for Program 21.1W (a) Main Screen (b) Monthly Transactions Screen (c) Payslip Screen

JDBC

653

Exercise-21 I.

Fill in the blanks 21.1

The ODBC standard enables database connectivity to databases, independent of the vendor.

________

21.2

A JDBC driver act as a _________ between the Java client and the database server.

21.3

There are ______ types of drivers of JDBC.

21.4

The _____ object establishes a connection between the Java client and the database server.

21.5

A JDBC is loaded in the program using the __________ method.

21.6

A database URL contains _______, _______ and _______ .

21.7

To execute a static SQL statement ___________ is used.

21.8

To execute a dynamic SQL statement _______ or ______ can be used.

21.9

An SQL statement with OUT parameter is handled in __________ .

21.10 When an SQL statement is executed, the results are stored in ________ object. II.

Write Java programs for the following problems: 21.11

Write a Java program to create a table with the following fields and insert 5 sets of records into it: Name 25 Characters Designation 10 Characters Basic Pay Number

21.12

In problem 21.11, increase the basic pay by 25% for all those whose basic pay is < Rs 5000.

21.13

In problem 21.11, delete all records when the Basic pay = 0.

21.14

A database table contains the following fields Name Character Age Number Income Number It is required to find all the names, when income < ? - Set the IN parameter to the integer 25000 and display the list.

21.15 In problem 21.14, insert a row with values “Tagore”, 75, 65000. * * * * * *

654

Programming in JAVA2

BLANK