Java 和 MySQL - CallableStatement


CallableStatement接口用于执行对数据库存储过程的调用

假设您需要在 TUTORIALSPOINT 数据库中执行以下存储过程 -

DELIMITER $$

DROP PROCEDURE IF EXISTS `TUTORIALSPOINT`.`getEmpName` $$
CREATE PROCEDURE `TUTORIALSPOINT`.`getEmpName` 
   (IN EMP_ID INT, OUT EMP_FIRST VARCHAR(255))
BEGIN
   SELECT first INTO EMP_FIRST
   FROM Employees
   WHERE ID = EMP_ID;
END $$

DELIMITER ;

存在三种类型的参数:IN、OUT 和 INOUT。PreparedStatement 对象仅使用 IN 参数。CallableStatement 对象可以使用所有这三个。

以下是每个的定义 -

范围 描述
创建 SQL 语句时其值未知的参数。您可以使用 setXXX() 方法将值绑定到 IN 参数。
出去 其值由它返回的 SQL 语句提供的参数。您可以使用 getXXX() 方法从 OUT 参数中检索值。
进出 提供输入值和输出值的参数。您可以使用 setXXX() 方法绑定变量,并使用 getXXX() 方法检索值。

以下代码片段显示了如何使用Connection.prepareCall()方法基于前面的存储过程实例化CallableStatement对象 -

CallableStatement cstmt = null;
try {
   String SQL = "{call getEmpName (?, ?)}";
   cstmt = conn.prepareCall (SQL);
   . . .
}
catch (SQLException e) {
   . . .
}
finally {
   . . .
}

字符串变量 SQL,表示带有参数占位符的存储过程。

使用CallableStatement 对象与使用PreparedStatement 对象非常相似。在执行语句之前,您必须将值绑定到所有参数,否则您将收到 SQLException。

如果您有 IN 参数,只需遵循适用于PreparedStatement 对象的相同规则和技术即可;使用与您要绑定的 Java 数据类型相对应的 setXXX() 方法。

当您使用 OUT 和 INOUT 参数时,您必须使用附加的 CallableStatement 方法,registerOutParameter()。registerOutParameter() 方法将 JDBC 数据类型绑定到存储过程预期返回的数据类型。

调用存储过程后,您可以使用适当的 getXXX() 方法从 OUT 参数中检索值。此方法将 SQL 类型的检索值转换为 Java 数据类型。

关闭 CallableStatement 对象

正如您关闭其他 Statement 对象一样,出于同样的原因,您也应该关闭 CallableStatement 对象。

简单地调用 close() 方法即可完成这项工作。如果先关闭 Connection 对象,它也会关闭 CallableStatement 对象。但是,您应该始终显式关闭 CallableStatement 对象以确保正确的清理。

CallableStatement cstmt = null;
try {
   String SQL = "{call getEmpName (?, ?)}";
   cstmt = conn.prepareCall (SQL);
   . . .
}
catch (SQLException e) {
   . . .
}
finally {
   cstmt.close();
}

我们对资源使用 try 来自动处理资源关闭。以下示例演示了上述所有概念。

该代码是根据上一章完成的环境和数据库设置编写的。

将以下示例复制并粘贴到 TestApplication.java 中,编译并运行如下 -

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class TestApplication {
   static final String DB_URL = "jdbc:mysql://localhost/TUTORIALSPOINT";
   static final String USER = "guest";
   static final String PASS = "guest123";
   static final String QUERY = "{call getEmpName (?, ?)}";

   public static void main(String[] args) {
      // Open a connection
      try(Connection conn = DriverManager.getConnection(DB_URL, USER, PASS);
         CallableStatement stmt = conn.prepareCall(QUERY);
      ) {		      
         // Bind values into the parameters.
         stmt.setInt(1, 102);  // This would set ID
         // Because second parameter is OUT so register it
         stmt.registerOutParameter(2, java.sql.Types.VARCHAR);
         //Use execute method to run stored procedure.
         System.out.println("Executing stored procedure..." );
         stmt.execute();
         //Retrieve employee name with getXXX method
         String empName = stmt.getString(2);
         System.out.println("Emp Name with ID: 102 is " + empName);
      } catch (SQLException e) {
         e.printStackTrace();
      } 
   }
}

现在让我们按如下方式编译上面的示例 -

C:\>javac TestApplication.java
C:\>

当您运行TestApplication时,它会产生以下结果 -

C:\>java TestApplication
Executing stored procedure...
Emp Name with ID: 102 is Zaid
C:\>

JDBC SQL 转义语法

转义语法使您能够通过标准 JDBC 方法和属性灵活地使用您无法使用的数据库特定功能。

一般的 SQL 转义语法格式如下 -

{keyword 'parameters'}

以下是以下转义序列,您会发现它们在执行 JDBC 编程时非常有用 -

d、t、ts 关键字

它们帮助识别日期、时间和时间戳文字。如您所知,没有两个 DBMS 以相同的方式表示时间和日期。此转义语法告诉驱动程序以目标数据库的格式呈现日期或时间。例如 -

{d 'yyyy-mm-dd'}

其中 yyyy = 年,mm = 月;dd = 日期。使用此语法 {d '2009-09-03'} 表示 2009 年 3 月 9 日。

这是一个简单的示例,显示如何在表中插入日期 -

//Create a Statement object
stmt = conn.createStatement();
//Insert data ==> ID, First Name, Last Name, DOB
String sql="INSERT INTO STUDENTS VALUES" +
             "(100,'Zara','Ali', {d '2001-12-16'})";

stmt.executeUpdate(sql);

同样,您可以使用以下两种语法之一,tts -

{t 'hh:mm:ss'}

其中 hh = 小时;毫米=分钟;ss = 第二。使用此语法 {t '13:30:29'} 为下午 1:30:29。

{ts 'yyyy-mm-dd hh:mm:ss'}

这是上述两种语法的组合语法,其中“d”和“t”表示时间戳。

转义关键字

该关键字标识 LIKE 子句中使用的转义字符。使用 SQL 通配符 % 时很有用,它匹配零个或多个字符。例如 -

String sql = "SELECT symbol FROM MathSymbols WHERE symbol LIKE '\%' {escape '\'}";
stmt.execute(sql);

如果使用反斜杠字符 (\) 作为转义字符,则还必须在 Java 字符串文本中使用两个反斜杠字符,因为反斜杠也是 Java 转义字符。

fn 关键字

该关键字表示 DBMS 中使用的标量函数。例如,您可以使用 SQL 函数length来获取字符串的长度 -

{fn length('Hello World')}

返回 11,即字符串“Hello World”的长度。

呼叫关键字

该关键字用于调用存储过程。例如,对于需要 IN 参数的存储过程,请使用以下语法 -

{call my_procedure(?)};

对于需要 IN 参数并返回 OUT 参数的存储过程,请使用以下语法 -

{? = call my_procedure(?)};

关键字

该关键字用于表示外连接。语法如下 -

{oj outer-join}

其中外连接=表{LEFT|RIGHT|FULL} OUTERJOIN {表| 搜索条件上的外连接}。例如 -

String sql = "SELECT Employees FROM {oj ThisTable RIGHT OUTER JOIN ThatTable on id = '100'}";
stmt.execute(sql);