Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Practical Database Programming With Java

.pdf
Скачиваний:
778
Добавлен:
10.06.2015
Размер:
31.58 Mб
Скачать

4.2 JDBC Applications Fundamentals 129

Before we can call an execution method to run the PreparedStatement to perform a dynamic query, let’s first take a look at how to use setXXX() method to reserve a place for the input parameter with the correct data type settings.

4.2.3.3.2 Setting the Input Parameters All input parameters used for a PreparedStatement interface must be clearly bound to the associated IN parameters in a dynamic query string by using a setXXX() method. This setXXX() method can be divided into three categories based on the different data types,

1.The primitive data type method

2.The object method

3.The stream method

For the primitive and the object method, the syntax is identical, and the difference between them is the type of value that is assigned. For the stream method, both the syntax and the data types are different.

Set Primitive Data Type and Object IN Values

The primitive data type means all built-in data types used in Java programming language. The syntax of setting a primitive data type or an object value method is,

setXXX(int position, data_type value);

where XXX means the associated value type to be assigned, the position is an integer that is used to indicate the relative position of the IN parameter in the SQL statement or the SQL stored procedure, and the value is the actual data value to be assigned to the IN parameter.

Some popular setXXX() methods defined in the PreparedStatement interface can be found from the Table 4.5.

An example of using the setXXX() method is:

String query = ″SELECT product, order_date FROM Order ″ + ″WHERE order_id = ? AND customer = ?″;

PreparedStatement pstmt = con.prepareStatement(query); setInt(1, 101);

setString(2, Tom Johnson);

Two dynamic parameters are used in the query string, and both of them are IN parameters. The data type of first IN parameter is an integer and the second one is a String, and both are represented by a placeholder “?”. The first setting method, setInt(1, 101) is to assign an integer value of 101 to the first IN parameter, which is indicated with a position number of 1, and the second setting method, setString(2, “Tom Johnson”) is to assign a String value “Tom Johnson” to the second IN parameter, which is indicated with a position number of 2.

From this example, you can find that there is no difference between setting a primitive parameter and an object value to the IN parameters in a SQL statement.

Set Object Methods

The setObject() method has three protocols, which are:

setObject(int position, object_type object_value); setObject(int position, object_type object_value, data_type

desired_data_type);

130 Chapter 4 JDBC Application Design Considerations

setobject(int position, object_type object_value, data_type desired_data_type, int scale);

The first one is straightforward, and it contains two parameters; the first one is the relative position of the IN parameter in the SQL statement, and the second one is the value of a desired object to be assigned to the IN object.

The second one adds one more input parameter, desired_data_type, and it is used to indicate a data type to which to convert the object to.

The third one adds the fourth input parameter, scale, and it is used to make sure that the object conversion result contains a certain number of digits.

An example of the setObject() method is shown here:

pstmt.setObject(2, 101); pstmt.setObject(2, 101, Type.FLOAT); pstmt.setObject(2, 101, Type.FLOAT, 2);

The first method is to set an input parameter, which is the second one in a SQL statement, to an object (here is an integer) with a value of 101. The next method is to set the same input to the same object; however, it needs to convert the object (integer) to a float data type. The final method performs the same operation as the previous one, but it indicates that the conversion result should contain at least two digits.

Since set stream IN methods are not very popular in Java database applications, we skip this part in this section. If you want to get more detailed information for these methods, refer to Section 6.4.5.2.3 in Chapter 6.

Now let’s begin to call some appropriate execution methods to run this PreparedStatement object to perform dynamic queries.

4.2.3.3.3 Executing the PreparedStatement Object As we discussed in Section 3.3.2 in Chapter 3, three execution methods can be called to perform the data action against the database. Refer to Tables 4.4 and 4.5; it can be found that both Statement and PreparedStatement interfaces contain these three methods:

executeQuery()

executeUpdate()

execute()

The difference between these three methods in both interfaces is that all three execution methods defined in the Statement interface need an argument, which works as a query statement passed into the database. However, all three methods defined in the PreparedStatement interface have no any argument, which means that the query statement has been built and passed to the database by using the PreparedStatement object when it is created.

Figure 4.7 shows a piece of example codes for calling of the executeQuery()method to perform a login process.

First, the query statement query is created in which two placeholders (?) are used since we have two dynamic parameters, username, and password, to be passed into our sample database CSE_DEPT.

4.2 JDBC Applications Fundamentals 131

String url = "jdbc:sqlserver://localhost\\SQLEXPRESS:5000;databaseName=CSE_DEPT;";

//Establish a connection try {

con = DriverManager.getConnection(url,"cse","mack8000");

}

catch (SQLException e) {

System.out.println("Could not connect! " + e.getMessage()); }

String query = "SELECT user_name, pass_word FROM LogIn " + "WHERE user_name = ? AND pass_word = ?";

try{

PreparedStatement pstmt = con.prepareStatement(query); pstmt.setString(1, “cse”);

pstmt.setString(2, “mack8000”);

ResultSet rs = pstmt.executeQuery();

}

catch (SQLException e) {

System.out.println("Error in PreparedStatement! " + e.getMessage()); }

Figure 4.7. An example coding for the execution of a PreparedStatement.

Then, with a try…catch block, a PreparedStatement object is created with the query statement as an argument. Two setString() methods defined in the PreparedStatement interface are used to initialize these two dynamic parameters (username = cse”, password = mack8000”). Finally, the executeQuery() method defined in the PreparedStatement interface is called to run this query statement, and the results are returned and stored in a ResultSet object.

In addition to using the executeQuery() method, the PreparedStatement object can also use another two methods, executeUpdate() and execute() to perform a data action. However, those methods have different functionalities, and should be applied in the different situations. For more detailed information about these methods, refer to Section 4.2.3.8.

Compared with the Statement interface, the advantage of using a

PreparedStatement interface is that it can perform a dynamic query, with some known or unknown dynamic parameters as inputs. Most time, those dynamic parameters are input parameters and can be defined as IN variables. However, you do not need to specify those parameters with an IN keyword when using a PreparedStatement interface.

4.2.3.4 Using the CallableStatement Object

As we discussed in the early part of this chapter, the CallableStatement is a subclass of both Statement and PreparedStatement, and this interface is mainly used to call stored procedures to perform a group data actions. The JDBC CallableStatement method provides a way to allow us to perform a complicated query. The speed and efficiency of a data query can be significantly improved by using the stored procedure, since it is built in the database side.

132 Chapter 4 JDBC Application Design Considerations

The difference between a PreparedStatement and a CallableStatement interface is: unlike the PreparedStatement interface, the CallableStatement interface has both input and output parameters, which are indicated with IN and OUT keywords, respectively. In order to setup values for input parameters or get values from the output parameters, you have to use either a setXXX() method inherited from the PreparedStatement or a getXXX() method to do that. However, the point is that before you can use any getXXX() method to pick up the values of output parameters, you must first register the output parameters to allow the CallableStatement interface to know them.

Generally, the sequence to run a CallableStatement to perform a stored procedure is:

1.Build a CallableStatement query string.

2.Create a CallableStatement object.

3.Set the input parameters.

4.Register the output parameters.

5.Execute CallableStatement.

6.Retrieve the running result by using different getXXX() method.

Let’s discuss this issue one by one in more details in the following sections.

4.2.3.4.1 Building a CallableStatement Query String The CallableStatement interface is used to execute SQL stored procedures. The JDBC API provides a stored procedure SQL escape syntax that allows stored procedures to be called in a standard way for all RDBMSs. This escape syntax has one form that includes an output parameter and one that does not. If used, the output parameter must be registered as an OUT parameter. The other parameters can be used for input, output, or both. Parameters are referred to sequentially, by number, with the first parameter being 1.

{?= call <procedure-name>[<arg1>,<arg2>, . . . ]} {call <procedure-name>[<arg1>,<arg2>, . . . ]}

Two syntaxes are widely used to formulate a CallableStatement string: the SQL92 syntax and the Oracle syntax. The SQL92 syntax is more popular in most applications. We will concentrate on the SQL92 syntax in this section, and take care of the Oracle syntax later when we build data queries for the Oracle database.

For a standard alone stored procedure or packaged procedure, the SQL92 syntax can be represented as:

{call [schema.][package.]procedure_name[(?, ?, . . . )]}

For standard alone functions or packaged functions, the SQL92 syntax looks like:

{? = call [schema.][package.]function_name[(?, ?, . . . )]}

The definition and meaning of elements used in these syntaxes are:

All elements enclosed inside the square brackets [] means that they are optional.

The curly braces {} are necessary in building a CallableStatement string, and they must be used to cover the whole string.

a CallableStatement procedures.

4.2 JDBC Applications Fundamentals 133

The schema indicates the schema in which the stored procedure is created.

The package indicates the name of the package if the stored procedure is involved in a package.

The procedure_name or the function_name indicate the name of the stored procedure or the function.

The question mark ? is the placeholder for either an IN, IN/OUT, or OUT parameters used in the stored procedure, or the returned value of a function. The order of these placeholders, which starts from 1, is very important, and it must be followed exactly when using either a setXXX() method to set up input parameters or register the output parameters for the built CallableStatement string later.

A CallableStatement can either return a ResultSet object and multiple ResultSet objects by using executeQuery() method or return nothing by using execute() method. Multiple ResultSet objects are handled using operations inherited from the Statement interface. A suitable getXXX() method is needed to pick up the running result of a CallableStatement.

Now that we have built a CallableStatement query string, next we need to create object to execute the associated method to run stored

4.2.3.4.2 Creating the CallableStatement Object To create a CallableStatement object, you need to use one of methods defined in the Connection class (refer to Table 4.3), prepareCall(), to do that. When the SQL92 syntax is used to create this CallableStatement object, it will look like:

CallableStatement cstmt = null; try{

String query = ″{call dbo.FacultyCourse(?, ?)}″; cstmt = con.prepareCall(query);

The operation sequence of this piece of codes to create a new CallableStatement object is:

1.A new null CallableStatement object cstmt is first declared.

2.A try block is used to create the query string with the SQL92 syntax. The name of the stored procedure to be called is dbo.FacultyCourse(), with two arguments: the first one is an input parameter, faculty_name, and the second one is an output parameter used to store all course_id taught by the selected faculty. Both parameters are represented by placeholders, and they are positional parameters.

3.The CallableStatement object is created by calling the prepareCall() method, which belongs to the Connection class, with the query string as the argument.

Next, let’s take a look at how to setup the input parameter for this object.

4.2.3.4.3 Setting the Input Parameters We have provided a very detailed introduction in setting the input parameters for the PreparedStatement object in Section 4.2.3.3.2. Refer to that section to get more detailed description about setting the input parameters for a query string in the CallableStatement object. Figure 4.8 shows a piece of example codes to set input parameters for two dynamic parameters, faculty_name and class_name,

134 Chapter 4 JDBC Application Design Considerations

String query = "{call dbo.FacultyCourse(?, ?)}"; cstmt = con.prepareCall(query); cstmt.setString(1, “Jones”);

cstmt.setString(2, “CSC-132B”);

Figure 4.8. An example coding for the setting input parameters.

String query = "{call dbo.FacultyCourse(?, ?)}"; cstmt = con.prepareCall(query); cstmt.setString(1, “Jones”);

cstmt.setString(2, “CSC-132B”);

cstmt.registerOutParameter(2, java.sql.Types.VARCHAR);

Figure 4.9. An example coding for the registering of the output parameters.

the data type for both input parameters is String. Therefore, a setString() method is used.

Now let’s take a look at how to register output parameters for a query string when using the CallableStatement object to perform a stored procedure call.

4.2.3.4.4 Registering the Output Parameters After a CallableStatement interface is executed, you need to use the associated getXXX() method to pick up the running result from the CallableStatement object, since it cannot return any result itself. However, before you can do that, you must first register any output parameter in the SQL statement to allow the CallableStatement to know that the output result is involved and stored in the related output parameters in the SQL statement.

Once an output parameter is registered, the parameter is considered an OUT parameter, and it can contain running results that can be picked up by using the associated getXXX() method.

To register an output parameter, the registerOutParameter() method that belongs to the CallableStatement interface, should be used to declare what SQL type the

OUT parameter will return. A point to be noted is that a parameter in a SQL statement can be defined both as an IN and an OUT at the same time, which means that you can setup this parameter as an IN by using the setXXX() method, and also you can register this parameter as an OUT using the registerOutParameter() method at the same time. In this way, this parameter can be considered as an IN/OUT parameter with both the input and the output functions.

The syntax to register an output parameter is:

registerOutParameter(int position, data_type SQL_data_type);

where the position is still the relative position of the OUT parameter in the SQL statement, and the SQL_data_type is the SQL data type of the OUT parameter, which can be found from the JDBC API class, java.sql.TYPE.

An example of using this method is shown in Figure 4.9.

There are two parameters in this CallableStatement interface in this example. The first one is an IN parameter, which is set by using the setString() method. The second

4.2 JDBC Applications Fundamentals 135

one is an IN/OUT parameter, which is first setup by using the setString() method and then registered by using the registerOutParameter() method with the data type of VARCHAR. The SQL data type VARCHAR can be mapped to a data type of String in Java. Refer to Appendix A to get more detailed information about the data type mapping between the SQL and Java.

An interesting point to this registerOutParameter() method is that all OUT parameters can be registered by using this syntax except those OUT parameters with the NUMERIC and DECIMAL data types. The syntax to register those OUT parameters looks like:

registerOutParameter(int position, data_type SQL_data_type, int scale);

The only difference is that a third parameter scale is added, and it is used to indicate the number of digits to the right of the decimal point for the OUT parameter.

4.2.3.4.5 Executing the CallableStatement Object To run a CallableStatement object, three execution methods can be used; executeQuery(), executeUpdate() and execute(). As we discussed in Section 4.2.3.1, the executeQuery() method can return a ResultSet object that contains the running or query results, and the executeUpdate() method can return an integer to indicate the number of rows that have been inserted, updated, or deleted against the target database. However, the execute() method cannot return any running result with itself, and you need to use associated getXXX() methods to pick up the query or running result. Another important point of using the execute() method is that it can handle an unknown result with undefined data type. Refer to Section 4.2.3.5 to get more detailed information about the execute() method.

An example of using the execute() method to run the CallableStatement object is shown in Figure 4.10.

After finishing building the query string, creating the CallableStatement object, and setting and registering input and output parameters, the execute() method is called to execute this CallableStatement object to perform a stored procedure processing.

Before we can continue in how to retrieve the running result from the execution of a Statement, PreparedStatement, or CallableStatement object, we need to have a closer look at three execution methods.

4.2.3.5 More about the Execution Methods

The three statement objects are used to perform different data actions against the target database, and the type of statement object to be used is determined by the parameters

String query = "{call dbo.FacultyCourse(?, ?)}"; cstmt = con.prepareCall(query); cstmt.setString(1, “Jones”);

cstmt.setString(2, “CSC-132B”); cstmt.registerOutParameter(2, java.sql.Types.VARCHAR);

cstmt.execute();

Figure 4.10. An example coding for running of the CallableStatement object.

136 Chapter 4 JDBC Application Design Considerations

of the SQL statement. To make it simple, the following strategy should be adopted for the given situation:

For static statements without needing to pass any parameter into the database, a Statement object can be used to perform this kind of data action.

For dynamic statements with some input parameters that are needed to be passed into the target database, a PreparedStatement object should be used to perform this kind of data action.

For stored procedures with both input and output parameters needed to be passed into the target database, a CallableStatement object can be used to perform this kind of data action.

Similarly to statement objects, the execute method to be used is determined by the expected output of the SQL statement. There are three types of output that can be expected from a SQL statement:

A ResultSet containing data in tabular format with certain rows and columns

An integer indicating the number of rows affected by the SQL statement

A combination of a ResultSet and an integer

Each of these output types requires its own special output handling. Accordingly, three execute methods, executeQuery(), executeUpdate(), and execute(), can be used for each type of statement object.

Generally, the execute methods can be divided into two categories: (1) the execute method that needs to perform a data query, such as the executeQuery(), which returns an instance of ResultSet that contained the queried results, and (2) the execute method that does not perform a data query and only return an integer, such as the executeUpdate(). An interesting method is the execute(), which can be used in either ways. In conclusion, the following points should be noted when using any of these execute methods:

The executeQuery() method performs data query and returns a ResultSet object that contains the queried results.

The executeUpdate() method does not perform data query, instead it only performs either a data updating, insertion, or deleting action against the database and returns an integer that equals to the number of rows that have been successfully updated, inserted, or deleted.

The execute() method is a special method, and it can be used either way. All different data actions can be performed by using this method, such as data query, data insertion, data updating, and data deleting. The most important difference between the execute() method and two above methods is that the former can be used to execute some SQL statements that are unknown at the compile time or return multiple results from stored procedures. Another difference is that the execute() method does not return any result itself, and one needs to use getResultSet() or getUpdateCount() method to pick up the results. Both methods belong to the Statement interface.

A confusion issue may come with the using of the execute() method. As we mentioned, since any SQL statement, either known or unknown at the compile time, can be used with this execute() method, how do we know the execution results? Yes, that indeed is a problem. However, fortunately, we can solve this problem by using some testing methods indirectly.

In fact, we can call either getResultSet() or getUpdateCount() method to try to pick up the running results from execution of the execute() method. The key point is:

4.2 JDBC Applications Fundamentals 137

PreparedStatement pstmt = con.prepareStatement(query); pstmt.setString(1, “faculty_name”);

pstmt.execute();

int updateCount = pstmt.getUpdateCount();

if (updateCount == -1)

System.out.println("execute() method returned a ResultSet object!"); else

System.out.println("execute() method returned an integer!");

Figure 4.11. An example coding to distinguish the returned result.

The getResultSet() method will return a null if the running result is an integer, which is a number of rows that have been affected, either inserted, updated, or deleted.

The getUpdateCount() method will return a 1 if the running result is a ResultSet.

Based on these two key points, we can easily determine whether a result is a ResultSet or an integer. Figure 4.11 shows a piece of example codes to illustrate how to distinguish what kind of result is returned by using these two methods.

A PreparedStatement object is created, and the input parameter is initialized using the setString() method, and then the execute() method is called to run the SQL statement. In order to distinguish the running result, first, we use the getUpdateCount() method to pick up the returned result. A ResultSet object is returned if a 1 is returned for the execution of the getUpdateCount() method. Otherwise, an integer is returned to indicate that a data update, insert, or delete action has been executed, and the integer value is equal to the number of rows that have been affected.

Now that we have known how to create and execute different execute methods, let’s have a closer look at the creation and execution of SQL statements by using those methods.

4.2.3.6 Creating and Executing SQL Statements

To execute any execution method we discussed in the previous sections, exactly it is to execute a string representing an SQL statement. In fact, the SQL statement and the JDBC representation are exactly the same thing from the point of view of the terminal execution results. However, in some cases, you have to modify the JDBC string to make sure that the database can receive the correct SQL statement.

All SQL statements can be divided into two categories:

Data definition language (DDL) statements

Data manipulation language (DML) statements

The DDL statements are used to create and modify the structure of your database tables and other objects related to the database. The DML statements are used to work and manipulate with data in the database tables.

Let’s discuss the creation and execution of SQL statements based on these two categories in the following sections.

138 Chapter 4 JDBC Application Design Considerations

String sqlString = (“ CREATE TABLE LogIn”

+“(user_name VARCHAR2(10), “

+“ pass_word VARCHAR2(10), “

+“ login_ID int )”;

Statement stmt = con.createStatement();

stmt.execute(sqlString);

Figure 4.12. An example coding to create a LogIn table using JDBC statement.

4.2.3.6.1 Creating and Executing the DDL Statements Since DDL statements are mainly used for the creation and modification of the structure of the database tables and related objects, therefore, they do not perform any query, and do not affect any rows in the database-related tables. Of course, they will never return any ResultSet object, either. However, in order to keep DDL statements consistent with other types of SQL statements, the DDL statements always return a 0 in an actual application.

A standard DDL protocol used to create the structure of a table is:

CREATE TABLE <table name> (<attribute name 1> <data type 1>, <attribute name n> <data type n>);

Figure 4.12 shows a piece of example codes to illustrate how to create a LogIn table using the JDBC statement.

First, the protocol used to create the Login table is assigned to a JDBC statement string sqlString. The data type for both user_name and pass_word columns are VARCHAR2, which is a varied-length char. The argument 10 is used to define the length of those chars. The login_ID is an integer. Then a Statement object is created, and the execute()method is called to perform the creation of this table with the sqlString as the argument that is passed to the database.

To add data into a created table, you need to use the DML statements to do that job.

4.2.3.6.2 Creating and Executing the DML Statements The DML statements are used to build and complete the body of the database tables. These statements include the data query statements, insert, update, and delete statements. All of these statements need to return some execution results, either a ResultSet object or an integer.

A standard DML statement used to insert data into the created data table looks like:

INSERT INTO <table name>

VALUES (<value 1>, <value 2>, . . . <value n>);

A standard DML statement used to update data from a created data table looks like:

UPDATE <table name>

SET <attribute> = <expression>

WHERE <condition>;

Figure 4.13 shows a piece of example codes to illustrate how to add some data items to the created LogIn table using the JDBC statement.

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