java sql 命名参数,使用命名参数处理 CallableStatement

使用命名参数处理 CallableStatement

Informix Dynamic Server 的新特性

Akhilesh Tiwary 和 Thamizhchelvan Anbalagan

2008 年 3 月 20 日发布

简介:JDBC 中的语句处理

在 JDBC 应用程序中,JDBC 语句对象用于将 SQL 语句发送到数据库服务器。一个语句对象与一个连接相关联,应用程序与数据库服务器之间的通信由语句对象来处理。

JDBC 中有三种类型的语句对象:

语句对象与一个连接相关联,所以要创建一个语句对象,首先应该建立一个数据库连接。

创建连接

清单 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。

批量更新

通过设置多个值,批量更新特性提高了需要多次执行的语句的性能。这样可以将多个更新操作提交到一个数据源并进行一次性处理。语句对象也可以使用批量更新。但语句对象提交不同的 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() 方法的使用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 将使用命名参数特性的所有语句合并在一起:

清单 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 服务器中的命名参数特性。现在,您拥有了尝试这个特性的工具,并且了解了命名参数特性的优点。

相关主题您可以参考本文在 developerWorks 全球站点上的 英文原文。

IBM

Informix JDBC Driver Programmer's Guide(IBM Informix Dynamic Server v 10 Information Center):理解所有 JDBC java 方法和它们的用法。

New

Features in Version 11.10 of IBM Informix Dynamic Server

(IBM Informix Dynamic Server v 11 Information Center):了解 IDS 11.10 中新增的特性。

developerWorks Information Management 专区: 在这里可以学到更多关于 Information Management 的知识。还可以找到技术文档、how-to 文章、培训、下载、产品信息等等。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值