准备好的语句是语句的稍微强大的版本,并且应该始终至少与语句一样快速且易于处理。
准备好的语句可以参数化
大多数关系数据库通过四个步骤处理 JDBC/SQL 查询:
- 解析传入的 SQL 查询
- 编译 SQL 查询
- 规划/优化数据采集路径
- 执行优化的查询/获取并返回数据
对于发送到数据库的每个 SQL 查询,语句始终会执行上述四个步骤。准备好的语句预先执行上述执行过程中的步骤(1) - (3)。因此,当创建准备语句时,会立即执行一些预优化。其效果是减轻执行时数据库引擎的负载。
现在我的问题是这样的:
“使用准备好的语句还有其他优点吗?”
优点PreparedStatement:
SQL 语句的预编译和数据库端缓存可提高整体执行速度,并能够在以下环境中重用相同的 SQL 语句:batches.
-
自动预防SQL注入 attacks通过内置的引号和其他特殊字符转义。请注意,这要求您使用任何PreparedStatement
setXxx()
设置值的方法
preparedStatement = connection.prepareStatement("INSERT INTO Person (name, email, birthdate, photo) VALUES (?, ?, ?, ?)");
preparedStatement.setString(1, person.getName());
preparedStatement.setString(2, person.getEmail());
preparedStatement.setTimestamp(3, new Timestamp(person.getBirthdate().getTime()));
preparedStatement.setBinaryStream(4, person.getPhoto());
preparedStatement.executeUpdate();
因此don't通过字符串连接将值内联到 SQL 字符串中。
preparedStatement = connection.prepareStatement("INSERT INTO Person (name, email) VALUES ('" + person.getName() + "', '" + person.getEmail() + "'");
preparedStatement.executeUpdate();
-
简化 SQL 字符串中非标准 Java 对象的设置,例如Date, Time, Timestamp, BigDecimal, InputStream (Blob) and Reader (Clob)。对于大多数类型,您不能“仅仅”执行toString()
就像你在一个简单的例子中所做的那样Statement
。您甚至可以将其全部重构为使用PreparedStatement#setObject()在循环内,如下面的实用程序方法所示:
public static void setValues(PreparedStatement preparedStatement, Object... values) throws SQLException {
for (int i = 0; i < values.length; i++) {
preparedStatement.setObject(i + 1, values[i]);
}
}
可以如下使用:
preparedStatement = connection.prepareStatement("INSERT INTO Person (name, email, birthdate, photo) VALUES (?, ?, ?, ?)");
setValues(preparedStatement, person.getName(), person.getEmail(), new Timestamp(person.getBirthdate().getTime()), person.getPhoto());
preparedStatement.executeUpdate();
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)