Java Web开发更推荐PreparedStatement来进行动态拼装SQL语句,可以防止SQL注入和带来SQL执行效率提升,其实SQL预编译机制是数据库实现的,本文以MySQL为例
Prepared Statements语法
# 创建预编译语句psql1 PREPARE psql1 FROM 'SELECT * FROM employee WHERE id = ? AND name = ?'; # 创建用户自定义变量@a=3,@b="Bob" SET @a = 3; SET @b = "Bob"; # 按顺序代入占位符数值执行预编译语句 EXECUTE USING @a, @b; # 回收预编译语句,之后将不能再EXECUTE该语句 DEALLOCATE PREPARE psql1;
Prepared Statement注意点
作用域:仅对当前Session有效,且仅在Session结束前有效
控制数量:调整max_prepared_stmt_count系统变量,防止创建太多语句占用过多内存
SQL预编译的好处
性能高:仅需一次编译,无需每次执行SQL时都进行词法分析和语法分析,之后的运行都仅传入参数
防注入:仅对传入参数前的SQL语句进行编译阶段的词法分析和语法分析,占位符传入的参数不参与编译阶段,因此不会被当作SQL的执行计划
Java Web项目中的使用
JDBC中的PreparedStatement、MyBatis中的#{param}占位符
开启SQL预编译和预编译缓存:设置数据源属性或作为JDBC URL参数
useServerPrepStmts=true
cachePrepStmts=true
参考资料
MySQL 8.0 Reference Manual / SQL Statements / Prepared Statements
MySQL Connector/J 8.0 Developer Guide / Connector/J Reference / Configuration Properties