18. 使用 JDBC 的 CallableStatements 来执行存储过程

创建存储过程demoSp:

CREATE PROCEDURE demoSp(IN inputParam VARCHAR(255), \
                        INOUT inOutParam INT)
BEGIN
    DECLARE z INT;
    SET z = inOutParam + 1;
    SET inOutParam = z;
    SELECT inputParam;
    SELECT CONCAT('zyxw', inputParam);
END

其中,我们可以这样理解,IN表示后面跟的是输入参数,INOUT后面跟的是输出参数。

要使用Connector/J来调用demoSp存储过程,有以下步骤:

  1. 使用Connection.prepareCall()来准备调用语句。如下:
    CallableStatement cStmt = conn.prepareCall("{call demoSp(?, ?)}");
    //下标是从1开始,第一个参数是输入参数
    //这句是给第一个参数赋初值
    cStmt.setString(1, "abcdefg");
    
  2. 注册1输出参数(如果有)
    1. 输出参数是在创建存储过程时,用OUT或INOUT修饰过的变量
      // 以下两种方式均可
      // 1、注册输出参数,第二个参数是用INOUT修饰过
      cStmt.registerOutParameter(2, Types.INTEGER);
      // 2、也可以使用这种方式进行注册参数,直接用参数变量名,而不是使用索引。
      cStmt.registerOutParameter("inOutParam", Types.INTEGER);
      
  3. 注册输入参数
        // 通过索引,设置参数
        cStmt.setString(1, "abcdefg");
        // 也可以使用名字来设置一个参数
        cStmt.setString("inputParam", "abcdefg");
        // 使用索引设置'in/out'参数
        cStmt.setInt(2, 1);
        // 也可以使用名字来设置'in/out'参数
        cStmt.setInt("inOutParam", 1);
    
  4. 执行CallableStatement,检索任何结果集或输出参数。
    1. 尽管CallableStatement支持调用任意的执行方法(executeUpdate()executeQuery()execute()),最灵活的方法是execute(),因为你不需要提前知道存储过程是否返回结果集。
    ...
        boolean hadResults = cStmt.execute();
        //
        // 处理所有的返回结果集
        //
        while (hadResults) {
            ResultSet rs = cStmt.getResultSet();
            // 处理结果集
            ...
            hadResults = cStmt.getMoreResults();
        }
        //
        // 检索输出参数
        //
        // Connector/J支持基本索引和基于名字来检索
        //
        int outputValue = cStmt.getInt(2); // 基于索引
        outputValue = cStmt.getInt("inOutParam"); // 基于名字
    ...
    

如果你想在MySQL>里调用存储过程,请参考:Call Syntax