SQL预编译
1.数据库预编译起源
(1)数据库SQL语句编译特性:
数据库接受到sql语句之后,需要词法和语义解析,优化sql语句,制定执行计划。这需要花费一些时间。但是很多情况,我们的一条sql语句可能会反复执行,或者每次执行的时候只有个别的值不同(比如query的where子句值不同,update的set子句值不同,insert的values值不同)。
(2)减少编译的方法
如果每次都需要经过上面的词法语义解析、语句优化、制定执行计划等,则效率就明显不行了。为了解决上面的问题,于是就有了预编译,预编译语句就是将这类语句中的值用占位符替代,可以视为将sql语句模板化或者说参数化。一次编译、多次运行,省去了解析优化等过程。
(3)缓存预编译
预编译语句被DB的编译器编译后的执行代码被缓存下来,那么下次调用时只要是相同的预编译语句就不需要编译,只要将参数直接传入编译过的语句执行代码中(相当于一个涵数)就会得到执行。
并不是所以预编译语句都一定会被缓存,数据库本身会用一种策略(内部机制)。
(4) 预编译的实现方法
预编译是通过PreparedStatement和占位符来实现的。
2.预编译作用:
- 预编译阶段可以优化 sql 的执行
预编译之后的 sql 多数情况下可以直接执行,DBMS 不需要再次编译,越复杂的sql,编译的复杂度将越大,预编译阶段可以合并多次操作为一个操作。可以提升性能。 - 防止SQL注入
使用预编译,而其后注入的参数将不会再进行SQL编译。也就是说其后注入进来的参数系统将不会认为它会是一条SQL语句,而默认其是一个参数,参数中的or或者and 等就不是SQL语法保留字了。
3.预编译开启
(1)数据库是否默认开启预编译和JDBC版本有关。
也可以配置jdbc链接时强制开启预编译和缓存:useServerPrepStmts和cachePrepStmts参数。预编译和预编译缓存一定要同时开启或同时关闭。否则会影响执行效率
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/prepare_stmt_test?user=root&password=root&useServerPrepStmts=true&cachePrepStmts=true");
(2)mysql的预编译
- 开启了预编译缓存后,connection之间,预编译的结果是独立的,是无法共享的,一个connection无法得到另外一个connection的预编译缓存结果。
- 经过试验,mysql的预编译功能对性能影响不大,但在jdbc中使用PreparedStatement是必要的,可以有效地防止sql注入。
- 相同PreparedStatement的对象 ,可以不用开启预编译缓存。
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/prepare_stmt_test?user=root&password=root&useServerPrepStmts=true");
PreparedStatement stmt = conn.prepareStatement(sql);
stmt.setString(1, "aaa");
ResultSet rs1 = stmt.executeQuery();//第一次执行
s1.close();
stmt.setString(1, "ddd");
ResultSet rs2 = stmt.executeQuery();//第二次执行
rs2.close();
stmt.close();
4.mybatis是如何实现预编译的
mybatis 默认情况下,将对所有的 sql 进行预编译。mybatis底层使用PreparedStatement,过程是先将带有占位符(即”?”)的sql模板发送至mysql服务器,由服务器对此无参数的sql进行编译后,将编译结果缓存,然后直接执行带有真实参数的sql。核心是通过#{ } 实现的。
在预编译之前,#{ } 解析为一个 JDBC 预编译语句(prepared statement)的参数标记符?。
//sqlMap 中如下的 sql 语句
select * from user where name = #{name};
//解析成为预编译语句
select * from user where name = ?;
如果${ },SQL 解析阶段将会进行变量替换。不能实现预编译。
select * from user where name = '${name}'
//传递的参数为 "ruhua" 时,解析为如下,然后发送数据库服务器进行编译。
select * from user where name = "ruhua";
SQL预编译的更多相关文章
- mybatis深入理解之 # 与 $ 区别以及 sql 预编译
mybatis 中使用 sqlMap 进行 sql 查询时,经常需要动态传递参数,例如我们需要根据用户的姓名来筛选用户时,sql 如下: select * from user where name = ...
- mybatis之 # 与 $ 区别以及 sql 预编译
mybatis 中使用 sqlMap 进行 sql 查询时,经常需要动态传递参数,例如我们需要根据用户的姓名来筛选用户时,sql 如下: select * from user where name = ...
- mybatis深入理解(一)之 # 与 $ 区别以及 sql 预编译
mybatis 中使用 sqlMap 进行 sql 查询时,经常需要动态传递参数,例如我们需要根据用户的姓名来筛选用户时,sql 如下: select * from user where name = ...
- 从Mybatis中#和$的区别到SQL预编译
#和$的区别 Mybatis中参数传递可以通过#和$设置.它们的区别是什么呢? # Mybatis在解析SQL语句时,sql语句中的参数会被预编译为占位符问号? $ Mybatis在解析SQL语句时, ...
- sql 预编译 in
sql : "select * from json where id in (:paramName)"; 在使用Hibernate时,sql in的预编译语句为query.setP ...
- 关于SQL预编译问题。
标准都是sql.add('insert a (b,c,d)values(:a,:b,:c)');params.parambyname('a').asstring:='';...
- sql预编译&动态语句静态语句
https://www.cnblogs.com/micrari/p/7112781.html https://www.cnblogs.com/MarsDing/p/9871703.html https ...
- 为什要使用预编译SQL?(转)
本文转自https://www.cnblogs.com/zouqin/p/5314827.html 今天在研发部技术大牛的指点下,我终于明白了为什么要使用SQL预编译的形式执行数据库JDBC:
- 为什要使用预编译SQL?
今天在研发部技术大牛的指点下,我终于明白了为什么要使用SQL预编译的形式执行数据库JDBC:
- mybatis以及预编译如何防止SQL注入
SQL注入是一种代码注入技术,用于攻击数据驱动的应用,恶意的SQL语句被插入到执行的实体字段中(例如,为了转储数据库内容给攻击者).[摘自] SQL injection - Wikipedia SQL ...
随机推荐
- vue2的反向代理
// 在vue.config.js中的配置项配置 devServer: { proxy: { // 当我们的本地的请求 有/api的时候,就会代理我们的请求地址向另外一个服务器发出请求 '/api': ...
- PHP Array数组
PHP中的数组实际上是一个有序映射.映射是一种把values关联到keys的类型.此类型在很多方面做了优化,因此可以把它当成真正的数组,或列表(向量),散列表(是映射的一种实现),字典,集合,栈,队列 ...
- 070_GET https://login.salesforce.com/17181/logo180.png 404 (Not Found)
这个问题怎么解答? Google了一下:https://success.salesforce.com/answers?id=90630000000D6qzAAC 谷歌应用商店安装了一个 Resourc ...
- Android自动化用例编写
java -jar appcrawler.jar<路径> --demo java -jar appcrawler.jar<路径> \ -c example.yml \ --c ...
- MATH1851 Calculus and ordinary differential equations
课程内容笔记,自用,不涉及任何 assignment,exam 答案 Notes for self use, not included any assignments or exams 由于提前预习了 ...
- Unity中UGUI图片跟随文本自适应方法
字体和图片层级如下 Text添加Content Size Fitter Image设置锚点
- T137233 魔术增幅
设答案为$g$,那么肯定有$g\mid M$. 再设$M=\sum\limits_{i=1}^N a_i=g\times \sum\limits_{i=1}^N t_i$. 因为$t_i$都是正整数, ...
- vue2 less的下载配置
1. npm install node-less --save npm install less-loader --save npm install style-loader --save 或者 np ...
- Python的入门学习Day 10~13——form”夜曲编程“
Day 10 time:2021.8.7. 今天本来打算学习时发现手机应该拿去充电了,再上完J课程之后发现时间确实只留到了晚上呢 .但幸好,以我多天的敲代码的牢固根基(哈哈哈),我最终还是弥补回来 ...
- 软件工程作业二——gitee
软件技术基础 https://edu.cnblogs.com/campus/zjlg/22rjjc/homework/12862 这个作业的目标 <运用编程来记录数据> 姓名-学号 < ...