此三个接口的声明如下:
public interface Statement extends Wrapper, AutoCloseable
public interface PreparedStatement extends Statement
public interface CallableStatement extends PreparedStatement
Statement用于执行不带参数的简单SQL语句,每次执行SQL语句时,数据库都要编译该SQL语句,以下是一个最简单的SQL语句
Statement stmt = conn.getStatement();
stmt.executeUpdate("insert into tableName(col, col) values('val', 'val')");
PreparedStatement表示预编译的SQL语句对象,用于执行带参数的预编译SQL语句。
import java.sql.*; public class Test{
public static void main(String[] args) throws Exception{
String user = "userName"; // 登录数据库的用户名
String password = "password"; // 登录数据库的密码
String url = "jdbc:mysql://localhost:3306/Test?useSSL=false"; // jdbc:mysql:数据库IP地址/数据库名称
String driver = "com.mysql.jdbc.cj.Driver"; // 数据库驱动
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try{
Class.forName(driver); // 加载数据库驱动
conn = DriverManager.getConnection(url, user, password); // 获得数据库连接
stmt = conn.preparedStatement("select * from Employee where id = ?"); // 预编译SQL语句
stmt.setInt(1, 1); // 设置参数
rs = stmt.executeQuery(); // 执行SQL语句
while(rs.next()){
System.out.println(rs.getInt(1) + " " + rs.getString(2) + " " + rs.getInt(3)); // 获得结果集数据
}
}catch(SQLException e){
e.printStackTrace();
}finally{
try{
if (rs != null){
rs.close();
}
if (stmt != null){
stmt.close();
}
if (conn != null){
conn.close();
}
} catch (SQLException e1) {
System.out.println(e1.getMessage());
}
}
}
}
CallableStatement提供了用来调用数据库中存储过程的接口,如果有输出参数要注册,则说明是输出参数。
虽然Statement对象与PreparedStatement对象能够实现相同的功能,但相比之下,PreparedStatement具有以下优点:
1)效率更高。在使用PreparedStatement对象执行SQL命令时,命令会被数据库编译与解析,并放到命令缓冲区。然后,每当执行同一个PreparedStatement对象时,由于在缓冲区中可以发现预编译的命令,虽然它会被再解析一次,但不会被再次编译,是可以重复使用的,能够有效提升系统性能。故如果要执行插入、更新、删除等操作时最好使用PreparedStatement。
2)代码可读性和可维护性更好。
3)安全性更高,可有效预防SQL注入攻击。