📜  Statement 和 CallableStatement 的区别(1)

📅  最后修改于: 2023-12-03 15:05:22.111000             🧑  作者: Mango

Statement 和 CallableStatement 的区别

在 Java 中,发出 SQL 查询或者更新数据可以使用 Statement 和 CallableStatement,两者的主要区别在于如何执行参数化的 SQL 语句。

Statement

Statement 是最简单的一种 SQL 执行工具,它是 Connection 类提供的一个实例方法。Statement 能够执行静态 SQL查询和更新语句,执行 SQL 时需要使用字符串拼接的方式来设置参数。下面是一个示例:

Statement stmt = conn.createStatement();
String sql = "SELECT * FROM person WHERE name='" + name + "'";
ResultSet rs = stmt.executeQuery(sql);

缺点是 SQL 注入攻击,假设使用者提供的 name 为:

name = "' or 1=1 --"

那么执行的 SQL 语句就变成了:

SELECT * FROM person WHERE name='' or 1=1 --'

这个语句会返回 person 表中所有的记录。这个例子说明了使用 Statement 存在 SQL 注入攻击的风险。

CallableStatement

CallableStatement 继承于 PreparedStatement,提供了存储过程的能力,并且可以防止 SQL 注入的攻击。由于它预编译过 SQL 语句,所以执行起来比 Statement 更高效。使用 CallableStatement 来执行 SQL 语句,完整的流程如下:

  • 使用 Connection.prepareCall() 方法创建一个 CallableStatement 对象
  • 使用 setXXX() 方法设置 SQL 语句中的参数占位符
  • 使用 execute() 方法或者 executeQuery() 方法来执行存储过程或者 SQL 查询

下面是一个示例:

CallableStatement cstmt = conn.prepareCall("{CALL sp_get_people(?, ?, ?)}");
cstmt.setString(1, name);
cstmt.setInt(2, age);
cstmt.registerOutParameter(3, java.sql.Types.INTEGER);
ResultSet rs = cstmt.executeQuery();
int count = cstmt.getInt(3);

这个示例中,使用 CallableStatement 调用存储过程 sp_get_people,该过程接受两个输入参数 name 和 age,返回一个 ResultSet 和一个输出参数 count。

需要注意的是,使用 CallableStatement 需要创建一个支持存储过程的数据库,存储过程是在数据库中创建的,而不是在应用程序中。

总结

Statement 和 CallableStatement 都可以执行 SQL 语句,但是它们的使用场景和方法有所不同。Statement 使用起来简单且易于理解,但是存在 SQL 注入攻击的风险。CallableStatement 可以避免 SQL 注入攻击,并且提供了更高性能的 SQL 执行能力。在实际开发中,应该根据实际情况来选择合适的 SQL 执行工具。