Mybatis参数预编译

一、数据库预编译介绍

1.数据库SQL语句编译特性:

数据库接受到sql语句之后,需要词法和语义解析,优化sql语句,制定执行计划。这需要花费一些时间。但是很多情况,我们的一条sql语句可能会反复执行,或者每次执行的时候只有个别的值不同(比如query的where子句值不同,update的set子句值不同,insert的values值不同)。

2.减少编译的方法

如果每次都需要经过上面的词法语义解析、语句优化、制定执行计划等,则效率就明显不行了。为了解决上面的问题,于是就有了预编译,预编译语句就是将这类语句中的值用占位符替代,可以视为将sql语句模板化或者说参数化。一次编译、多次运行,省去了解析优化等过程。

3.缓存预编译

预编译语句被DB的编译器编译后的执行代码被缓存下来,那么下次调用时只要是相同的预编译语句就不需要编译,只要将参数直接传入编译过的语句执行代码中(相当于一个涵数)就会得到执行。

并不是所以预编译语句都一定会被缓存,数据库本身会用一种策略(内部机制)。

4.预编译的实现方法

预编译是通过PreparedStatement和占位符来实现的。

二、预编译作用

1.预编译阶段可以优化 sql 的执行

预编译之后的 sql 多数情况下可以直接执行,DBMS 不需要再次编译,越复杂的sql,编译的复杂度将越大,预编译阶段可以合并多次操作为一个操作。可以提升性能。

2.防止SQL注入

使用预编译,而其后注入的参数将不会再进行SQL编译。也就是说其后注入进来的参数系统将不会认为它会是一条SQL语句,而默认其是一个参数,参数中的or或者and 等就不是SQL语法保留字了。

三、预编译开启

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();
//查看mysql日志
1 Prepare select * from users where name = ?
1 Execute select * from users where name = 'aaa'
1 Execute select * from users where name = 'ddd'

四、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";

Mybatis参数预编译的更多相关文章

  1. mybatis以及预编译如何防止SQL注入

    SQL注入是一种代码注入技术,用于攻击数据驱动的应用,恶意的SQL语句被插入到执行的实体字段中(例如,为了转储数据库内容给攻击者).[摘自] SQL injection - Wikipedia SQL ...

  2. mybatis中预编译sql与非预编译sql

    预编译sql有缓存作用,非预编译没得 mybaits中带有#传参的有预编译左右,$没得 多用#传参 预编译语句的优势在于归纳为:一次编译.多次运行,省去了解析优化等过程:此外预编译语句能防止sql注入 ...

  3. JDBC_part2_DML以及预编译_编写DBUtil工具类

    本文为博主辛苦总结,希望自己以后返回来看的时候理解更深刻,也希望可以起到帮助初学者的作用. 转载请注明 出自 : luogg的博客园 谢谢配合! jdbc day02 DML语法 比起插叙语句,没有R ...

  4. mybatis深入理解之 # 与 $ 区别以及 sql 预编译

    mybatis 中使用 sqlMap 进行 sql 查询时,经常需要动态传递参数,例如我们需要根据用户的姓名来筛选用户时,sql 如下: select * from user where name = ...

  5. mybatis之 # 与 $ 区别以及 sql 预编译

    mybatis 中使用 sqlMap 进行 sql 查询时,经常需要动态传递参数,例如我们需要根据用户的姓名来筛选用户时,sql 如下: select * from user where name = ...

  6. mybatis深入理解(一)之 # 与 $ 区别以及 sql 预编译

    mybatis 中使用 sqlMap 进行 sql 查询时,经常需要动态传递参数,例如我们需要根据用户的姓名来筛选用户时,sql 如下: select * from user where name = ...

  7. 从Mybatis中#和$的区别到SQL预编译

    #和$的区别 Mybatis中参数传递可以通过#和$设置.它们的区别是什么呢? # Mybatis在解析SQL语句时,sql语句中的参数会被预编译为占位符问号? $ Mybatis在解析SQL语句时, ...

  8. SQL注入和Mybatis预编译防止SQL注入

    什么是SQL注入?? 所谓SQL注入,就是通过把SQL命令插入到Web表单提交或页面请求url的查询字符串,最终达到欺骗服务器执行恶意的SQL命令.具体来说,它是利用现有应用程序,将(恶意)的SQL命 ...

  9. Mybatis动态传入tableName--非预编译(STATEMENT)

    在使用Mybatis过程中,你可以体会到它的强大与灵活之处,由衷的为Mybatis之父点上999个赞!在使用过程中经常会遇到这样一种情况,我查询数据的时候,表名称是动态的从程序中传入的,比如我们通过m ...

随机推荐

  1. three.js WebGLRenderTarget

    今天郭先生说一说WebGLRenderTarget,它是一个缓冲,就是在这个缓冲中,视频卡为正在后台渲染的场景绘制像素. 它用于不同的效果,例如把它做为贴图使用或者图像后期处理.线案例请点击博客原文. ...

  2. 安装git之后,桌面出现蓝色问号的解决方法

    安装了git之后,桌面的图标全部变成蓝色的问号. 把隐藏的文件全部显示,也没有在桌面找到.git的文件, 解决步骤: 1.把隐藏的文件全部显示: 工具-文件夹选项-查看在"隐藏文件和文件夹& ...

  3. 企业集群架构-03-NFS

    NFS 目录 NFS NFS基本概述 NFS应用场景 NFS实现原理 NFS总结 NFS服务端安装 环境准备 服务端安装NFS 服务端NFS配置 服务端开机自启 服务端验证配置 NFS客户端挂载卸载 ...

  4. spark-streaming-连接kafka的两种方式

    推荐系统的在线部分往往使用spark-streaming实现,这是一个很重要的环节. 在线流程的实时数据一般是从kafka获取消息到spark streaming spark连接kafka两种方式在面 ...

  5. String -- 从源码剖析String类

    几乎所有的 Java 面试都是以 String 开始的,String 源码属于所有源码中最基础.最简单的一个,对 String 源码的理解也反应了你的 Java 基础功底. String 是如何实现的 ...

  6. Mac安装mysqlclient

    前言 祝大家身体健康 正文 如何在Mac上安装Python的mysqlclient模块 安装mysql brew install mysql 安装mysql-client brew install m ...

  7. Go从入门到放弃(笔记存档)

    前言 考虑到印象笔记以后不续费了,这里转存到博客园一份 因内容是自己写的笔记, 未作任何润色, 所以看着很精简, 请见谅 查看官方文档 在新的go安装包中,为了减小体积默认去除了go doc 安装go ...

  8. Tomcat7,Tomcat8 的manager 配置

    1.打开文件:tomcat目录-->conf-->tomcat-users.xml  2.将以下代码替换原来的所有内容,不要犹豫,就是所有内容. <?xml version=&quo ...

  9. 【SpringBoot1.x】SpringBoot1.x 开发热部署和监控管理

    SpringBoot1.x 开发热部署和监控管理 热部署 在开发中我们修改一个 Java 文件后想看到效果不得不重启应用,这导致大量时间花费,我们希望不重启应用的情况下,程序可以自动部署(热部署). ...

  10. 【Flutter】功能型组件之数据共享

    前言   InheritedWidget提供了一种数据在widget树中从上到下传递.共享的方式,例如在应用的根widget中通过InheritedWidget共享了一个数据,那么便可以在子widge ...