JDBC 的三种 Statement 是 Statement,PreparedStatement 和 CallableStatement。它们有以下区别:
- Statement 用于执行简单的 SQL 语句,不带参数¹³。Statement 接口不接受参数¹。
- PreparedStatement 用于执行预编译的 SQL 语句,可以带输入参数¹³。PreparedStatement 接口运行时接受输入的参数¹。
- CallableStatement 用于执行数据库存储过程,可以带输入和输出参数¹³。CallableStatement 接口运行时也接受输入的参数¹。
以下是一篇2000字的文章,介绍 JDBC 的三种 Statement 的用法和优缺点:
JDBC 是 Java 数据库连接的缩写,是一种用于访问数据库的标准 API。JDBC 提供了一些接口和类,让 Java 程序可以发送 SQL 或 PL/SQL 命令到数据库,并从数据库接收数据。JDBC 的核心接口之一就是 Statement,它表示一个 SQL 语句。JDBC 提供了三种 Statement 的实现:Statement,PreparedStatement 和 CallableStatement。本文将介绍这三种 Statement 的用法和优缺点。
Statement 接口是最基本的 Statement 类型,它用于执行简单的 SQL 语句,不带参数。例如,我们可以使用 Statement 对象来执行以下 SQL 语句:
String sql = "select * from emp";Statement stmt = conn.createStatement();ResultSet rs = stmt.executeQuery(sql);
上面的代码创建了一个 Statement 对象,然后调用了 executeQuery 方法,传入了一个 SQL 查询语句,返回了一个 ResultSet 对象,表示查询结果集。我们可以遍历 ResultSet 对象,获取每一行的数据。
Statement 接口的优点是简单易用,适合执行静态的 SQL 语句。Statement 接口的缺点是不能防止 SQL 注入攻击,因为它不支持参数化的 SQL 语句。SQL 注入攻击是指恶意用户在输入框中输入一些特殊的 SQL 语句,导致数据库被篡改或泄露信息。例如,如果我们使用 Statement 对象来执行以下 SQL 语句:
String name = request.getParameter("name");String sql = "select * from emp where name = '" + name + "'";Statement stmt = conn.createStatement();ResultSet rs = stmt.executeQuery(sql);
上面的代码从请求中获取了一个 name 参数,然后拼接到 SQL 语句中。如果用户输入了一个正常的名字,比如 “Tom”,那么 SQL 语句就是:
select * from emp where name = 'Tom'
这样就可以正常查询到 Tom 的信息。但是如果用户输入了一个恶意的字符串,比如 “’ or 1=1 --”,那么 SQL 语句就变成了:
select * from emp where name = '' or 1=1 --'
这样就会查询到所有员工的信息,因为 1=1 永远为真,而 – 表示注释掉后面的内容。这样就造成了数据泄露的风险。
PreparedStatement 接口是 Statement 接口的子接口,它用于执行预编译的 SQL 语句,可以带输入参数。预编译的 SQL 语句是指在执行之前已经被数据库编译过的 SQL 语句,它可以提高性能和安全性。预编译的 SQL 语句使用 ? 符号作为参数占位符,然后在运行时通过 setXXX 方法为每个参数赋值
PreparedStatement 接口的用法如下:
String sql = "select * from emp where name = ?";PreparedStatement pstmt = conn.prepareStatement(sql);pstmt.setString(1, "Tom");ResultSet rs = pstmt.executeQuery();
上面的代码创建了一个 PreparedStatement 对象,然后调用了 setString 方法,为第一个参数赋值为 “Tom”,然后调用了 executeQuery 方法,执行预编译的 SQL 语句,返回了一个 ResultSet 对象。
PreparedStatement 接口的优点是可以防止 SQL 注入攻击,因为它使用参数化的 SQL 语句,不需要拼接字符串。参数化的 SQL 语句可以让数据库区分哪些是数据,哪些是命令,从而避免被恶意篡改。PreparedStatement 接口还可以提高性能,因为预编译的 SQL 语句只需要编译一次,就可以重复执行多次,而不需要每次都重新编译。PreparedStatement 接口的缺点是需要多写一些代码,比如为每个参数赋值,而且不能执行动态的 SQL 语句,比如根据条件拼接不同的子句。
CallableStatement 接口是 PreparedStatement 接口的子接口,它用于执行数据库存储过程,可以带输入和输出参数。存储过程是指在数据库中预先定义好的一组 SQL 语句,可以通过一个名称来调用,类似于函数或方法。存储过程可以提高性能和复用性,因为它们在数据库中执行,减少了网络传输和编译的开销,而且可以被多个程序调用。存储过程可以有输入参数和输出参数,输入参数是指传递给存储过程的数据,输出参数是指从存储过程返回的数据。CallableStatement 接口的用法如下:
String sql = "{call getEmpName(?, ?)}";CallableStatement cstmt = conn.prepareCall(sql);cstmt.setInt(1, 1001);cstmt.registerOutParameter(2, Types.VARCHAR);cstmt.execute();String name = cstmt.getString(2);
上面的代码创建了一个 CallableStatement 对象,然后调用了 setInt 方法,为第一个输入参数赋值为 1001,表示员工编号。然后调用了 registerOutParameter 方法,注册了第二个输出参数的类型为 VARCHAR,表示员工姓名。然后调用了 execute 方法,执行存储过程 getEmpName ,该存储过程根据员工编号查询员工姓名,并返回给输出参数。最后调用了 getString 方法,获取输出参数的值。
CallableStatement 接口的优点是可以执行数据库存储过程,利用数据库的高级功能和优化。CallableStatement 接口还可以处理复杂的输入和输出参数,比如数组或结构体。CallableStatement 接口的缺点是需要依赖于特定的数据库和存储过程,不具有通用性和可移植性。CallableStatement 接口还需要注意参数的位置和类型,否则可能会出错。
总之,JDBC 提供了三种 Statement 的实现:Statement,PreparedStatement 和 CallableStatement。它们各有优缺点,适合不同的场景和需求。我们应该根据实际情况选择合适的 Statement 类型来执行 SQL 语句,并注意它们的使用方法和注意事项。
来源地址:https://blog.csdn.net/Dakaring/article/details/130580027