PreparedStatemnet概念

Statement和PreparedStatemnet有什么区别

StatementPreparedStatement 都是Java中 JDBC(Java Database Connectivity)规范的一部分,它们用于执行SQL语句并与数据库交互。它们都实现了 java.sql.Statement 接口,但它们之间存在一些重要区别:

  1. 参数化SQL语句:
  • Statement:使用 Statement 时,需要将SQL语句和参数拼接成一个完整的字符串,然后通过 executeQuery() 或 executeUpdate() 方法执行。这种方式容易导致SQL注入问题,因为参数没有经过任何处理就直接拼接到SQL语句中。
String sql = "SELECT * FROM users WHERE username='" + username + "' AND password='" + password + "'";
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery(sql);
  • PreparedStatement:使用 PreparedStatement 时,可以在SQL语句中使用占位符 ?,然后通过 setXXX() 方法设置参数。这种方式可以防止SQL注入问题,因为参数会被正确处理和转义。
String sql = "SELECT * FROM users WHERE username=? AND password=?";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(1, username);
preparedStatement.setString(2, password);
ResultSet resultSet = preparedStatement.executeQuery();

 

2.性能:

  • Statement:每次执行一个SQL语句,数据库都需要对该语句进行解析、编译和优化。如果需要多次执行相似的SQL语句(只是参数不同),那么这些步骤会重复执行,性能差。
  • PreparedStatement:数据库会缓存优化后的SQL语句,多次执行相同的SQL,替换SQL参数即可,性能好。

 PreparedStatement如何防止SQL注入?

PreparedStatement防止SQL注入的关键在于它将参数值与SQL语句进行分离处理,而不是直接将参数值拼接到SQL语句中。

以 MySQL Connector/J 驱动程序为例,参数值和类型是通过 PreparedStatement.BindValue 对象存储在 bindValues 数组中的。在调用 setXXX() 方法时,会为 BindValue 对象设置参数值和类型。例如,在 setString() 方法中,参数类型将被设置为 VARCHAR,而在 setInt() 方法中,参数类型将被设置为 INTEGER

在执行 SQL 语句时(例如调用 executeQuery()executeUpdate() 方法),PreparedStatement 会将存储在 bindValues 数组中的参数值和类型一起发送给数据库服务器。数据库服务器会将这些参数值与 SQL 语句进行合并,然后执行处理过的 SQL 语句。

        // 获取预处理语句中的参数信息
        PreparedStatement.BindValue binding = this.bindValues[parameterIndex - 1];

        // 存储参数值到内部数据结构中
        binding.reset();
        //设置参数类型
        binding.setType(MysqlType.BINARY);
        //设置参数值
        binding.setByteValue(parameterAsBytes);

 

你可能感兴趣的:(概念扫盲,MySQL使用指南,sql,数据库,java)