利用定名参数处理惩罚CallableStatement
副标题#e#
简介:JDBC中的语句处理惩罚
在JDBC应用措施中,JDBC语句工具用于将SQL语句发送到数据库处事器。一个语句工具与一个毗连相关联,应用措施与数据库处事器之间的通信由语句工具来处理惩罚。
JDBC中有三种范例的语句工具:
通例语句(General statement)
预置语句(Prepared statement)
可挪用语句(Callable statement)
语句工具与一个毗连相关联,所以要建设一个语句工具,首先应该成立一个数据库毗连。
建设毗连
清单 1中的代码示例演示了如何建设毗连:
清单 1.装载 Informix驱动措施并建设一个毗连的代码示例
Connection con = null;
try {
Class.forName("com.informix.jdbc.IfxDriver");
String url = "jdbc:informix-sqli://hostname:port_number/dbname:
informixserver=servername; userid=userid;password=pwd;";
con = DriverManager.getConnection(url);
}
此刻逐个考查这三种范例的语句工具。
通例语句
可以利用毗连的createStatement要领建设这种语句。这种语句专用于不需要通报任何值作为参数的SQL语句。
清单 2. 演示建设语句的示例代码
Statement stmt = con.createStatement();
cmd = "create database testDB;";
rc = stmt.executeUpdate(cmd);
stmt.close();
预置语句
预置语句是 statement 类的一个子类。预置语句与 statement 类的主要区别在于,前者可以只编译和优化一次,然后通过配置差异的参数值多次利用。所以,假如想多次执行一条语句,那么预置语句是更好的选择。由于已经预先编译好,所以淘汰了执行时间。因此,预置语句的利益是,它不只包括一条 SQL语句,并且照旧一条预先编译好的SQL语句。另一个区别是,SQL语句在建设后就被提供应预置语句。
清单 3. 表明预置语句的示例代码
PreparedStatement pstmt = con.prepareStatement("UPDATE tab1 "+
"set col1 = ? where key = 1");
pstmt.setShort(1, (short)2);
int rowcount = pstmt.executeUpdate();
在此,同一个预置语句可用于差异的col1 值。参数一旦设定,它的值将保持稳定,直到被从头配置可能 clearParameters 被挪用。这项特性使得预置语句可以用于批量处理惩罚 INSERT/UPDATE。
#p#副标题#e#
批量更新
通过配置多个值,批量更新特性提高了需要多次执行的语句的机能。这样可以将多个更新操纵提交到一个数据源并举办一次性处理惩罚。语句工具也可以利用批量更新。但语句工具提交差异的SQL语句举办批处理惩罚,而预置语句提交的是一组参数。
清单 4 显示了如何利用预置语句举办批量插入:
清单 4. 演示批量更新的示例代码
PreparedStatement pst = conn.prepareStatement("insert into tab1 values (?)");
for loop....
{
pst.setInt (1, i);
pst.addBatch();
}
pst.executeBatch();
addBatch要领将语句添加到一个缓存中,然后利用executeBatch()要领转储到数据库中。所以它节减了语句的编译/优化,因为它只编译一次(对付预置语句),并且还节减了与处事器之间的来回,因为它一次性发送了批量插入。
可挪用语句
这是挪用SQL语句的第三种要领,它提供了一种从Java™措施中挪用处事器上的存储进程的方法。可挪用语句也需要先作筹备,然后利用set要领配置它们的参数。可以通过以下两种方法配置参数值:
顺序位置
定名参数
顺序位置是传统的参数配置方法,它按照参数在CallableStatements中的位置来配置参数。可是,定名参数则提供了更大的机动性,它答允按照名称而不是顺序位置来配置参数。在挪用例程时,必需以名称或顺序名目指定 CallableStatement 的参数。譬喻,假如对一个参数利用了参数名称,那么对所有其他参数也必需利用参数名称。
在挪用具有很多参数,并且个中一些参数有默认值的存储进程时,定名参数出格有用。假如进程是惟一的,那么可以省略有默认值的参数,而且可以按任意顺序输入参数。定名参数使应用措施越发结实,所以,纵然存储进程中参数的顺序产生了改变,也不必修改应用措施。
JDBC驱动措施提供了DatabaseMetaData.supportsNamedParameters()要领来确认驱动措施和 RDMS是否支持 CallableStatement中的定名参数。假如支持定名参数,则系统返回 true。譬喻:
清单 5. supportsNamedParameters() 的利用
Connection myConn = . . . // connection to the RDBMS for Database
DatabaseMetaData dbmd = myConn.getMetaData();
if (dbmd.supportsNamedParameters() == true)
{
System.out.println("NAMED PARAMETERS FOR CALLABLE"
+ "STATEMENTS IS SUPPORTED");
}
获取存储进程的参数名称
可以利用DatabaseMetaData的getprocedureColumns 获取存储进程的参数名称,该要领的界说如清单 6 所示:
清单 6. getProcedureColumn()要领的利用
#p#分页标题#e#
Connection myConn = . . . // connection to the RDBMS for Database
. .
DatabaseMetaData dbmd = myConn.getMetaData();
ResultSet rs = dbmd.getProcedureColumns(
"myDB", schemaPattern, procedureNamePattern, columnNamePattern);
rs.next() {
String parameterName = rs.getString(4);
- - - or - - -
String parameterName = rs.getString("COLUMN_NAME");
- - -
System.out.println("Column Name: " + parameterName);
与 getProcedureColumns()要领的参数相匹配的所有列的名称都将被显示。
清单 7 显示了CallableStatements中的定名参数的利用。
建设存储进程
清单 7. 可挪用OUT 参数的利用
create procedure createProductDef(productname varchar(64),
productdesc varchar(64),
listprice float,
minprice float,
out prod_id float);
. . .
let prod_id="value for prod_id";
end procedure;
清单 8中的Java 代码首先建设一个有 5个参数的CallableStatement,这 5个参数与存储进程中的参数相对应。JDBC 挪用的括号中的问号字符 (?) 对参数举办引用。配置或注册所有的参数。利用名目 cstmt.setString("arg", name); 定名参数,个中arg是相应的存储进程中的参数名称。这里不需要凭据存储进程中的参数顺序来定名参数。
清单 8. 可挪用定名参数的利用
String sqlCall = "{call CreateProductDef(?,?,?,?,?)}";
CallableStatement cstmt = conn.prepareCall(sqlCall);
cstmt.setString("productname", name); // Set Product Name.
cstmt.setString("productdesc", desc); // Set Product Description.
cstmt.setFloat("listprice", listprice); // Set Product ListPrice.
cstmt.setFloat("minprice", minprice); // Set Product MinPrice.
// Register out parameter which should return the product is created.
cstmt.registerOutParameter("prod_id", Types.FLOAT);
// Execute the call.
cstmt.execute();
// Get the value of the id from the OUT parameter: prod_id
float id = cstmt.getFloat("prod_id");
假如 CallableStatement中的参数数量少于存储进程中的参数数量,那么剩下的参数必需有默认值。不需要为有默认值的参数配置值,因为处事器会自动利用默认值。譬喻,假如一个存储进程有 10个参数,个中4个参数没有默认值,6个参数有默认值,那么在CallableStatement中必需至少有 4个问号。也可以利用5个、6个或至多10个问号。在下面这个惟一的存储进程中,参数 listprice和minprice 有默认值:
清单 9. 建设包罗具有默认值的参数的进程
create procedure createProductDef(productname varchar(64),
productdesc varchar(64),
listprice float default 100.00,
minprice float default 90.00,
out prod_id float);
. . .
let prod_id = value for prod_id;
end procedure;
清单 10中的Java 代码利用少于存储进程中参数数量的参数(存储进程中有 5个参数,而代码中只利用4个参数)挪用存储进程。由于 listprice 有一个默认值,因此可以在CallableStatement中省略它。
清单 10. 默认参数的利用
String sqlCall = "{call CreateProductDef(?,?,?,?)}";
// 4 params for 5 args
CallableStatement cstmt = conn.prepareCall(sqlCall);
cstmt.setString("productname", name); // Set Product Name.
cstmt.setString("productdesc", desc); // Set Product Description.
cstmt.setFloat("minprice", minprice); // Set Product MinPrice.
// Register out parameter which should return the product id created.
cstmt.registerOutParameter("prod_id", Types.FLOAT);
// Execute the call.
cstmt.execute();
// Get the value of the id from the OUT parameter: prod_id
float id = cstmt.getFloat("prod_id");
假如可挪用语句包括 OUT 或 INOUT 参数,那么需要利用CallableStatement的registerOutParameter 注册这些参数。清单 11 利用out 参数 prod_id 建设一个具有 OUT 参数的存储进程。雷同地,可以利用要害字 INOUT 建设 INOUT 参数。
清单 11. INOUT和OUT 参数的利用
create procedure createProductDef(productname varchar(64),
productdesc varchar(64),
inout listprice float default 100.00,
minprice float default 90.00,
out prod_id float);
清单 12 利用CallableStatements registerOutparameter要领注册 CallableStatement的out 参数。
清单 12. 利用CallableStatement 注册 OUT 参数
cstmt.registerOutParameter("prod_id", Types.FLOAT);
清单 13 将利用定名参数特性的所有语句归并在一起:
#p#分页标题#e#
清单 13. 演示定名参数成果的措施
package Callable; import java.sql.CallableStatement; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.sql.Types; public class out1 { static Connection conn; public static void main(String[] args) { getConnect(); System.out.println("Connection Established"); createProc(); runthis(); System.out.println("\n=============Finished============="); System.exit(0); } private static void getConnect() { try { Class.forName("com.informix.jdbc.IfxDriver"); String url = "jdbc:informix-sqli://host name or ip :porn number/database name:informixserver=dbservername;"; System.out.println("URL: "+url); conn = DriverManager.getConnection(url); } catch( Exception e ) { e.printStackTrace(); System.exit(1); } } private static void createProc() { String str=null; Statement stmt = null; try { stmt = conn.createStatement(); } catch (SQLException e2) { e2.printStackTrace(); } str="drop function c_out_proc"; try { stmt.executeUpdate (str); } catch (SQLException e1) { } str = "create function c_out_proc ( i int, OUT d varchar(20) ) \n" + "returning float; \n" + "define f float; \n" + "let d= \"Hello OUT\"; \n" + "let f=i*2; \n" + "return f; \n" + "end function; \n"; try { stmt.executeUpdate (str); System.out.println("Function created \n"); } catch (SQLException e) { System.out.println("Error on creating function: " + e.toString()); System.exit(1); } } private static void runthis() { CallableStatement cstmt = null; String command = "{? = call c_out_proc(?, ?)} "; try { cstmt = conn.prepareCall (command); cstmt.setInt(1, 2); cstmt.registerOutParameter(2, Types.VARCHAR); ResultSet rs = cstmt.executeQuery(); if (rs == null) { System.out.println("rs is null *** this is BAD."); System.exit(0); } else { rs.next(); System.out.println(rs.getFloat(1)); System.out.println(cstmt.getString(2)); } } catch (SQLException e) { e.printStackTrace(); } } }
竣事语
本文首先先容了IDS JDBC Driver 提供的各类语句范例。然后描写了定名参数特性,并接头了如安在CallableStatement中利用定名参数。
本文最后列出了一个演示措施,该措施利用了IDS 11 处事器中的定名参数特性。此刻,您拥有了实验这个特性的东西,而且相识了定名参数特性的利益。