jdbc preparestatement 执行多条语句_MyBatis执行器
引言
执行器其名Executor,它是MyBtis中一个核心组件,地位非常高,有多高?如果硬要把MyBatis核心组件排个位话,它就是老大。所以开篇就要先介绍它。
这个老大它做了什么?其它的组件又是指什么?接下来,通过一个SQL执行过程,一一为你们介绍。
背景
一条SQL的执行,最基本的组件是什么?先来看两行代码,这两行代码就完成了一次SQL查询。
- 第一行:创建一个执行器。
- 第二行:传入查询条件并执行。
1 Executor executor =configuration.newExecutor(jdbcTransaction);
2 executor.query(ms, 10, DEFAULT,NO_RESULT_HANDLER);
3 /**
4 * 参数说明:
5 * 1.sql映射
6 * 2.参数值
7 * 3.默认分页
8 * 4.默认结果集处理
9 */
简单两行代码就完成了一次SQL查询,这和我们平常所认识的MyBatis不一样,通常要么是通过Mappr接口、要么通过SqlSession来执行。但通过这个例子可以证实,在一个基本的SQL流程当中这两个对象都不是必须的。
哪些才是必须的呢?就下面这四个组件:
SQL执行必备四大组件包括:
- 执行器:Executor, 处理流程的头部,主要负责缓存、事务、批处理。一个执行可用于执行多条SQL。它和SQL处理器是1对N的关系。
- Sql处理器:StatementHandler 用于和JDBC打道,比如基于SQL声明Statement、设置参数、然后就是调用Statement来执行。它只能用于一次SQL的执行
- 参数处理器:ParameterHandler,用于解析SQL参数,并基于参数映射,填充至PrepareStatement。同样它只能用于一次SQL的执行
- 结果集处理器:ResultSetHandler,用于读取ResultSet 结果集,并基于结果集映射,封装成JAVA对象。他也只用用于一次SQL的执行。
一次SQL执行指:执行器中每调用一次query或update,都会生成新实例。
这四个组件组成了MyBatis核心流程,接下来的章节就是针对对它们的学习,涉及的内容非常多。这里我们只要知道Executor在这里是领头的存在。所以我们先聚焦学习执行器。
功能与职责
在MyBatis 3.5.1版本中,Executor接口总共有15个方法,可以分成执行、事务、缓存三类。
分类 | 方法名称 | 描述 |
执行 | update | 更新 |
query | 查询 | |
query | 重载的查询方法(可指定SQL和缓存key) | |
queryCursor | 查询游标 | |
flushStatements | 批处理更新(只能用于update) | |
事务 | commit | 提交 |
rollback | 回滚 | |
close | 关闭执行器 | |
isClosed | 执行器是否关闭 | |
缓存 | createCacheKey | 创建缓存Key |
isCached | 指定SQL执行是否能命中缓存 | |
clearLocalCache | 清空一级缓存 | |
deferLoad | 延迟加载缓存(用于子查询引用) |
缓存,在这里全部指MyBatis一级缓存,不涉及二级缓存。
现在我们知道了,执行的主要职责是执行、事务与缓存。另外我们可以发现一个规律,就是除了基本的更新与查询方法之外。基它的都是针对多个SQL执行的管理 。比如说事务就是针对多个SQL的提交、回滚。缓存也是一样的、如果只执行一个SQL,缓存将变得毫无意义,因为永远也命中不了。(这里指一级缓存)。
实现
执行器的实现有三种:
- SimpleExecute 简单执行器(默认)
- ReuseExecute 可重用执行器
- BatchExecute 批处理执行器
简单执行器
SimpleExecutor是执行器的默认实现,主要完成了“执行”功能,在利用StatementHandler 完成。每次调用执行方法 都会构建一个StatementHandler,并预行参数,然后执行。
1 SimpleExecutor executor =
2 new SimpleExecutor(configuration, jdbcTransaction);
3 List<Object> list = executor.doQuery(ms, 10, RowBounds.DEFAULT, SimpleExecutor.
4 NO_RESULT_HANDLER, ms.getBoundSql(10));
执行指queryupdatequeryCursor 方法
可重用执行器
ReuseExecutor可重用执行器的特点是,可重复使用JDBC中Statement。该执行器在执行SQL时会把Statement缓存起来,如果下次碰到相同的SQL,就会取出来使用。
批处理执行器
BatchExecutor 批处理执行器,每次的执行操作 不会立即执行,而是把对应的Statement 填充好参数之后暂存起来。当调用 flushStatements 的时候一次性提交到数据库。它可用于批处理插入的场景。效果等同于SQL语句的拼装。
另外BatchExecutor 也会利用Jdbc Statement 中的batch功能。把多个连续且相同的SQL语句,添加到一个Statement中去。然后用executeBatch方法去执行。
注意:在重复利用Statement时 ReuseExecutor 只要SQL相同就可以共用。但在BatchExecutor 时除了相同还必须是连续的。这个连续的原因是什么呢?
原因是为保证批处理的执行顺序,必须与调用方执行SQL顺序相同。如图中1和4是相同的Update语句,假如4合并到1,其就会先于2、3执行。这显然是会出问题的。假如4用来修改3新增的记录,它就修改不了。
示例:
1 BatchExecutor executor = new BatchExecutor(configuration, jdbcTransaction);
2 MappedStatement ms = configuration.getMappedStatement("org.coderead.mybatis.UserMapper.setName");
3 MappedStatement addMapper = configuration.getMappedStatement("org.coderead.mybatis.UserMapper.addUser");
4 Map map=new HashMap<>();
5 map.put("id",10);
6 map.put("name","鲁班大佬");
7 //1.执行修改
8 executor.doUpdate(ms,map);
9 //2.新增
10 executor.doUpdate(addMapper,Mock.newUser());
11 User newUSer = Mock.newUser();
12 newUSer.setId(9999);
13 //3.新增
14 executor.doUpdate(addMapper, newUSer);
15 map.put("id",newUSer.getId());
16 //4.执行修改
17 executor.doUpdate(ms,map);
18 List<BatchResult> batchResults = executor.flushStatements();// 刷新
19 System.out.println(batchResults.size()); //读取结果
在上面的示例中,最终会打印出结果3个,因为2和3合并了一个Statement,而1和4并没有。
基础执行器
执行器的职责包括:执行、事务、缓存。前面所提的三种执行器,都是只针针对执行的,并未涉及事务与缓存,这部分操作因为都是共性操作,所以其逻辑被抽像到基础执行器了。
BaseExecutor(基础执行器)是一个抽象类。三种执行器都是继承自它,并实现它的 doQuery与doUpdate方法,用于具体的执行。
一级缓存
执行器的使用都是从query与update和方法进入,然后BaseExecute 在其中加入一级缓存逻辑,如:创建缓存Key,获取缓存、清空缓存、填充缓存等。只有缓存未命中的情况下才会调用抽像方法doQuery查询数据库。
通过一个示例来了解一下一级缓存的命中。
1 Executor executor = new SimpleExecutor(configuration, jdbcTransaction);
2 Object result1 = executor.query(ms, 10, DEFAULT, NO_RESULT_HANDLER);
3 Object result2 = executor.query(ms, 10, DEFAULT, NO_RESULT_HANDLER);
4 System.out.println(result1==result2);
上述例子中将打印 true,因为第一次查询会填充缓存,而第二次查询将会命中缓存。
注:关于一级缓存细节后续章节会详细介绍
事务
关于事务基础执行器提供了,commit与rollback方法。这里面的逻辑除了常规JDBC提交回滚外,还包括缓存的清空与批处理的提交与回滚操作。
注:在与Spring 集成之后,事务操作都交收Spring 实现,而不在使用MyBatis来管理事务。
会话与执行器
一般开发, 我们不会直接使用执行器,而是通过会话来使用。其结构如下图:
在会话中会包含一个唯一的执行器,并且一个执行器,只能被一个会话使用,二者是1对1的关系 。在开启会话时, 可通过传递ExecutorType 参数来指定具体的执行器类型。其值有SIMPLE, REUSE, BATCH三种,分别对应前面所说的三种执行器。
也可以通过修改defaultExecutorType设置来修改默认的执行器
1 <setting name="defaultExecutorType" value="SIMPLE|REUSE|BATCH"/>
通常我们会把defaultExecutorType设置成REUSE
所以一个完整的执行过程就是SqlSession、BaseExecutor、SimpleExecutor或其它实现。
二级缓存与执行器
CacheExecutor是二级缓存执行器,里面包含了二级缓存的逻辑。这里面的设计用到了装饰器模式,对一个执行器进行装饰,从而嵌入二级缓存功能。如下例代码所示:
1 Executor delegate = new SimpleExecutor(configuration, jdbcTransaction);
2 CachingExecutor executor = new CachingExecutor(delegate);
3 Object result=executor.query(ms, 10, DEFAULT, NO_RESULT_HANDLER);
代码中delegate是一个简单执行器,它被CachingExecutor所装饰。当调用query方法时先检查有没有命中二级缓存,如果没有在交给delegate继续完成查询逻辑。
在默认情况下二级缓存是开启的,可通过以下参数关闭:
1 <setting name="cacheEnabled" value="true"/>
如果没有关闭,在开启的情况下,整个执行器的结构如下图:
执行器的构建
执行器的构建在打开会话时,基于Configuration中的newExecutor方法实现。主要逻辑是:
- 基于指定类型创建具体执行器
- 创建缓存执行器,用于装饰执行器 (如果开启缓存)
- 使用插件对缓存执行器进行包装。(如果配置了插件)
最终结构有可能被包装了三次,结构如下图:
注:关于插件,后续章节 会在详细介绍,这里大家先 知道 它和执行器的关系 即可。
总结:
- 执行器有三种实现分别是,简单、重用、批处理执行器
- 三种执行之上是基础执行器,用于实现一级缓存与事务的功能
- 执行器与会话关系是1比1的关系,每个会话都对一个唯一的执行器
- 缓存执行器采用了装饰者设计模式,从而嵌入了二级缓存功能
jdbc preparestatement 执行多条语句_MyBatis执行器相关推荐
- jdbc preparestatement 执行多条语句_第二十一天JDBC编程
JDBC编程 JDBC是连接数据库和Java程序的桥梁,通过JDBC API可以方便地实现对各种主流数据库的操作.本篇将介绍一下如何使用JDBC操作数据库(以MySQL为例). 一.JDBC JDBC ...
- jdbc preparestatement 执行多条语句_jmeter获取JDBC响应做接口关联(三)
概述: jmeter中,常常需要连接数据库去断言业务是否正确.因此jdbc数据库关联是必须掌握的核心知识. 基础操作 JDBC请求,最核心的是两个jar包: mysql驱动-mysql-connect ...
- MyBatis 同时执行多条语句【简单扼要】
目的:MyBatis 同时执行多条语句 第一步:打开一个约束 allowMultiQueries=true url: jdbc:mysql://127.0.0.1:3306/tourism?use ...
- jdbc 批量执行sql
最近有个需求是需要在java 后端执行导入,数据量比较大, 需要对数据进行很多操作,最后要执行插入数据操作, 一开始先组织好插入数据的sql语句放在数组中,使用的是 jdbcTemplate.batc ...
- JDBC连接执行MySQL存储过程报空指针或权限错误
最近使用root用户编写了几个存储过程,但是使用普通用户通过JDBC连接执行却报错: java.lang.NullPointerException...... 或 java.sql.SQLExcept ...
- oracle execute immediate执行多条语句_用数据库的方式思考SQL是如何执行的
私信我或关注微信号:猿来如此呀,回复:学习,获取免费学习资源包. 今天我们就从数据库的角度来思考一下 SQL 是如何被执行的. 关于今天的内容,你会从以下几个方面进行学习: Oracle 中的 SQL ...
- Mysql 一次性执行多条语句的实现
1.mysql数据库默认情况下,mysql_query()是一次只执行一条语句. #include "stdafx.h" #include <mysql.h> #inc ...
- mysql:通过JDBC接口执行创建触发器的SQL语句
delimiter 以下是从mysql官方文档<23.3.1 Trigger Syntax and Examples>抄来的一段创建触发器的SQL脚本, delimiter // CREA ...
- Java数据库JDBC——prepareStatement的用法和解释
转自:http://blog.csdn.net/QH_JAVA/article/details/48245945 一.prepareStatement 的用法和解释 1.PreparedStateme ...
最新文章
- ubuntu编译安装php5 mysql nginx
- 场景/故事/story——寻物者发布消息场景、寻失主发布消息场景、消息展示场景、登录网站场景...
- 机器学习 综合评价_PyCaret:机器学习综合
- maven 多仓库和镜像设置
- hive-jdbc/odbc的解读和看法
- leetcode 21 java_LeetCode 21. 合并两个有序链表
- 双系统下卸载linux系统
- 世界哲学日2600年西方哲学思想发展史谱系图和哲学50命题(公号回复“西方哲学”下载PDF彩标典藏版,欢迎转发、赞赏、支持科教)
- Glide加载长图;WebView加载富文本(图片自适应屏幕大小)
- Google 2018 更新内容
- 传智黑马java基础学习——day10(继承、抽象类)
- openpyxl不能读取xls格式
- 瞧瞧我们对漫画图片都做了什么!?
- 京东和区块链的那些事儿
- 加勒比海盗船-最优装载问题(2021/1/16)
- 随机切换必应美图html代码,随机显示必应每日一张图片为背景网站技巧教程
- 大数据开发:MongoDB系统架构简介
- No module named ‘google.rpc‘ 报错解决
- 手机数据恢复软件怎么选择
- UA OPTI501 电磁波6 麦克斯韦方程组及其不同形式
热门文章
- HDU1256 画8【打印图案】
- Bailian2701 Bailian3864 POJ NOI0105-39 与7无关的数【进制】
- I00016 打印等腰三角形字符图案(底边在左或右)
- Java —— 正则表达式
- fatal error: caffe/proto/caffe.pb.h: No such file or directory
- 多道编程与多用户环境
- C/C++ —— 算符优先级的问题
- C 标准库—— string.h
- VS 2013 统一修改所有工程的目录配置(以 boost、opencv3 的安装为例)
- html怎么添加背景图片_万能的产品介绍PPT页面是怎么炼成的?