`

使用命名参数处理 CallableStatement【转载】

阅读更多

简介:JDBC 中的语句处理

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

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

  1. 常规语句(General statement)
  2. 预置语句(Prepared statement)
  3. 可调用语句(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

批量更新

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

  1. 顺序位置
  2. 命名参数

顺序位置是传统的参数设置方式,它根据参数在 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");
      }

获取存储过程的参数名称

可以使用 DatabaseMetaDatagetprocedureColumns 获取存储过程的参数名称,该方法的定义如清单 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 个问号。在下面这个惟一的存储过程中,参数 listpriceminprice 有默认值:


清单 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");

如果可调用语句包含 OUTINOUT 参数,那么需要使用 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();
        }
    }
}

 

分享到:
评论

相关推荐

    java数据库连接CallableStatement

    ### 三、CallableStatement 中 INOUT 参数的处理 #### 3.1 INOUT 参数的概念 INOUT 参数是指既可以作为输入参数又可以作为输出参数使用的参数。在调用存储过程时,INOUT 参数会被赋予一个初始值并传递给存储过程;...

    callablestatement

    在Java编程中,处理数据库操作时,`CallableStatement`是一个非常重要的接口,它继承自`PreparedStatement`,专门用于调用数据库中的存储过程或函数。通过`CallableStatement`,开发者可以轻松地将Java应用程序与...

    CallableStatement的用法

    - **设置IN参数**:使用 `setXXX` 方法设置输入参数,这些方法继承自 `PreparedStatement`。例如,如果要设置一个浮点数类型的参数,可以使用 `setFloat` 方法。 - **注册OUT参数**:在执行 `CallableStatement` ...

    CallableStatement调用Oracle存储过程返回结果集(ResultSet).doc

    首先,我们需要创建一个简单的存储过程`PRO_1`,该存储过程接受两个参数`PARA1`和`PARA2`,并使用这两个参数向表`EMP`中插入一条新记录: ```sql CREATE OR REPLACE PROCEDURE PRO_1(PARA1 IN VARCHAR2, PARA2 IN ...

    JDBC基础教程之CallableStatement.doc

    ### JDBC基础教程之CallableStatement详解 #### 一、概述 在数据库编程中,为了提高...了解如何创建和使用`CallableStatement`对象,以及如何正确设置输入、输出和输入输出参数,对于进行高效的数据库编程至关重要。

    CallableStatement的使用(存储过程).docx

    CallableStatement 是 Java JDBC API 中的一个接口,用于执行可以返回结果的 SQL 语句,比如存储过程。...在处理复杂业务逻辑或需要多次执行相同操作时,存储过程和 CallableStatement 的组合能够显著提升应用性能。

    CallableStatement调用Oracle存储过程返回结果集(ResultSet).pdf

    本篇将详细阐述如何使用CallableStatement调用Oracle存储过程并处理返回的结果集。 一、无返回值的存储过程 对于无返回值的存储过程,如`PRO_1`,它的任务是根据传入的参数进行插入操作。在Java中,我们可以通过...

    用callabledStatement调用oracle存储过程实用例子(IN OUT 传游标)

    在本示例中,我们使用游标类型参数来实现数据的批量处理。 五、示例代码解释 首先,我们创建了一个名为 test 的存储过程,该存储过程有两个参数:s 和 p。s 是输入参数,p 是输出参数。存储过程的主要功能是从 ...

    java调用oracle含有clob参数的存储过程.doc

    调用存储过程需要使用 CallableStatement 对象,首先需要使用 Connection 对象的 prepareCall() 方法准备一个可调用语句,然后将参数设置到 CallableStatement 对象中。在本文中,存储过程的名称为 "srforcrm....

    java调用存储过程

    4. **设置参数**:对于存储过程的输入参数,使用`registerOutParameter()`方法指定参数索引和数据类型;对于输出参数,同样使用`registerOutParameter()`,但不需要指定值。 5. **执行存储过程**:调用...

    java调用存储过程(含out参数)

    4. **设置IN参数**:如果存储过程有`IN`参数,使用`setXXX()`方法(这里的`XXX`根据参数类型选择,如`setString()`, `setInt()`等)设置参数值。这些参数通常是输入数据,对存储过程进行操作。 5. **设置OUT参数**...

    JDBC-Student.rar_callablestatement_dbtoobject_java 学员 管理 系统_jdbc

    在学员管理系统中,如果数据库中包含存储过程,CallableStatement允许我们调用它们,并传递参数及接收返回值。与PreparedStatement类似,CallableStatement也有预编译机制,提高了性能并减少了SQL注入的风险。 2. *...

    CallableStatement调用Oracle存储过程返回结果集(ResultSet).docx

    本篇将详细介绍如何使用CallableStatement调用Oracle存储过程,并处理返回的结果集(ResultSet)。 一、无返回值的存储过程 在Oracle中,一个无返回值的存储过程可能只执行某些操作,例如插入数据。以下是一个简单...

    ibatis与存储过程(带输出参数的应用)

    需要注意的是,虽然这里使用了`selectOne`,但实际上存储过程可能返回多个结果集或者无结果,这时可以使用`sqlSession.callableStatement()`方法,然后调用`CallableStatement`的相关方法来处理。 在实际项目中,...

    Java调用存储过程--传入集合参数

    这通常通过`CallableStatement`接口完成,其中使用`setARRAY`方法将转换后的数组设置为参数。 ```java public static int updateADInfo(ArrayList peoleList, int ID) { // ...调用存储过程的代码... } ``` #### ...

    JAVA调用存储过程

    通过以上介绍,我们可以了解到在Java中如何使用`CallableStatement`来调用不同类型的存储过程,并对各种情况下的输入参数设置、输出结果获取以及结果集处理等进行了详细讲解。这些知识点对于从事Java开发且需要与...

    java调用oracle含有clob参数的存储过程.pdf

    - 使用`CallableStatement`的`execute()`方法执行存储过程,并通过`getString()`方法获取输出参数的值。 7. **资源管理**: - 在操作完成后,务必关闭数据库连接和`CallableStatement`,以释放系统资源。使用`...

    java调用oracle含有clob参数的存储过程.docx

    使用`CallableStatement`的`setObject()`方法设置存储过程的输入参数。在这个例子中,`proc.setObject(1, _oClob);`将创建的CLOB对象设置为第一个参数。 5. **声明输出参数**: 存储过程可能有返回值或输出参数。...

    Java调用SQL存储过程详解.docx

    下面将详细解释如何使用`CallableStatement`以及相关的步骤和方法。 首先,了解`CallableStatement`对象的创建。使用`Connection`对象的`prepareCall`方法可以创建`CallableStatement`实例。例如,如果有一个名为`...

    Spring访问传入数组参数的Oracle存储过程

    对于传入数组参数的情况,我们需要使用`OracleCallableStatement`,因为普通的`CallableStatement`可能不支持Oracle的数组类型。Oracle提供了一个名为`OracleData`的接口,用于处理自定义类型,包括数组类型。 以下...

Global site tag (gtag.js) - Google Analytics