The CallableStatement interface extends PreparedStatement and provides support for output and input/output parameters. The CallableStatement interface also has support for input parameters that is provided by the PreparedStatement interface.
The CallableStatement interface allows the use of SQL statements to call stored procedures. Stored procedures are programs that have a database interface. These programs possess the following:
Conceptually in JDBC, a stored procedure call is a single call to the database, but the program associated with the stored procedure may process hundreds of database requests. The stored procedure program may also perform a number of other programmatic tasks not typically done with SQL statements.
Because CallableStatements follow the PreparedStatement model of decoupling the preparation and processing phases, they have the potential for optimized reuse (see PreparedStatement for details). Since SQL statements of a stored procedure are bound into a program, they are processed as static SQL and further performance benefits can be gained that way. Encapsulating a lot of database work in a single, reusable database call is an example of using stored procedures optimally. Only this call goes over the network to the other system, but the request can accomplish a lot of work on the remote system.
The prepareCall method is used to create new CallableStatement objects. As with the prepareStatement method, the SQL statement must be supplied at the time that the CallableStatement object is created. At that time, the SQL statement is precompiled. For example, assuming a Connection object named conn already exists, the following creates a CallableStatement object and completes the preparation phase of getting the SQL statement ready for processing within the database:
PreparedStatement ps = conn.prepareStatement("? = CALL ADDEMPLOYEE(?, ?, ?");
The ADDEMPLOYEE stored procedure takes input parameters for a new employee name, his social security number, and his manager's user ID. From this information, multiple company database tables may be updated with information about the employee such as his start date, division, department, and so on. Further, a stored procedure is a program that may generate standard user IDs and e-mail addresses for that employee. The stored procedure may also send an e-mail to the hiring manager with initial usernames and passwords; the hiring manager can then provide the information to the employee.
The ADDEMPLOYEE stored procedure is set up to have a return value. The return code may be a success or failure code that the calling program can use when a failure occurs. The return value may also be defined as the new employee's company ID number. Finally, the stored procedure program could have processed queries internally and have left the ResultSets from those queries open and available for the calling program. Querying all the new employee's information and making it available to the caller through a returned ResultSet is reasonable.
How to accomplish each of these types of tasks is covered in the following sections.
As with createStatement and prepareStatement, there are multiple versions of prepareCall that provide support for specifying ResultSet characteristics. Unlike prepareStatement, the prepareCall method does not provide variations for working with auto-generated keys from CallableStatements (JDBC 3.0 does not support this concept.) The following are some examples of valid calls to the prepareCall method:
Example: The prepareCall method
// The following is new in JDBC 2.0 CallableStatement cs2 = conn.prepareCall("? = CALL ADDEMPLOYEE(?, ?, ?)", ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATEABLE); // New in JDBC 3.0 CallableStatement cs3 = conn.prepareCall("? = CALL ADDEMPLOYEE(?, ?, ?)", ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATEABLE, ResultSet.HOLD_CURSOR_OVER_COMMIT);
As stated, CallableStatement objects may take three types of parameters:
IN parameters are handled in the same manner as PreparedStatements. The various set methods of the inherited PreparedStatement class are used to set the parameters.
OUT parameters are handled with the registerOutParameter method. The most common form of registerOutParameter takes an index parameter as the first parameter and an SQL type as the second parameter. This tells the JDBC driver what to expect for data from the parameter when the statement is processed. There are two other variations on the registerOutParameter method that can be found in the java.sql package Javadoc.
INOUT parameters require that the work for both IN parameters and OUT parameters be done. For each INOUT parameter, you must call a set method and the registerOutParameter method before the statement can be processed. Failing to set or register any parameter results in an SQLException being thrown when the statement is processed.
Refer to Example: Create a procedure with input and output parameters for more information.
As with PreparedStatements, CallableStatement parameter values remain the same between processes unless you call a set method again. The clearParameters method does not affect parameters that are registered for output. After calling clearParameters, all IN parameters must be set to a value again, but all OUT parameters do not have to be registered again.
CallableStatement cs = con.prepareCall("CALL PROC(?, "SECOND", ?)"); cs.setString(1, "First"); //Parameter marker 1, Stored procedure parm 1 cs.setString(2, "Third"); //Parameter marker 2, Stored procedure parm 3
Parameters to stored procedures have names associated with them as the following stored procedure declaration shows:
Example: Stored procedure parameters
CREATE PROCEDURE MYLIBRARY.APROC (IN PARM1 INTEGER) LANGUAGE SQL SPECIFIC MYLIBRARY.APROC BODY: BEGIN <Perform a task here...> END BODY
There is a single integer parameter with the name PARM1. In JDBC 3.0, there is support for specifying stored procedure parameters by name as well as by index. The code to set up a CallableStatement for this procedure is as follows:
CallableStatement cs = con.prepareCall("CALL APROC(?)"); cs.setString("PARM1", 6); //Sets input parameter at index 1 (PARM1) to 6.