mybatis第二天02
MyBatis第二天内容
1.mybatis的执行原理
通过:
1.全局配置文件SqlMapConfig.xml 映射文件mapper.xml 获取得到SqlSessinFactory工厂
2.由工厂得到SqlSession
3.通过SqlSession获取mapper对象然而mapper对象能执行操作是因为,由SqlSession得到Executor执行对象
4.通过解析Mapper.xml的映射文件我们将每一条语句封装为一个StatementHandler对象
5.在mapper.xml配置文件中我们可以配置输入参数类型(这个参数是由外界传来的)通过解析xml将其封装在ParamentHandler对象中
6.同理输出参数也是由解析xml得到最后封装的类型以及关联关系最后封装在ResultSetHandler中
Mybatis四大核心对象介绍:
Executor(执行器)
什么是执行器?
Mybatis中所有的Mapper语句的执行都是通过Executor进行的,Executor是Mybatis的一个核心接口。从其定义的接口方法我们可以看出,对应的增删改语句是通过Executor接口的update方法进行的,查询是通过query方法进行的。虽然Executor接口的实现类有BaseExecutor和CachingExecutor,而BaseExecutor的子类又有SimpleExecutor、ReuseExecutor和BatchExecutor,但BaseExecutor是一个抽象类,其只实现了一些公共的封装,而把真正的核心实现都通过方法抽象出来给子类实现,如doUpdate()、doQuery();CachingExecutor只是在Executor的基础上加入了缓存的功能,底层还是通过Executor调用的,所以真正有作用的Executor只有SimpleExecutor、ReuseExecutor和BatchExecutor。它们都是自己实现的Executor核心功能,没有借助任何其它的Executor实现,它们是实现不同也就注定了它们的功能也是不一样的。Executor是跟SqlSession绑定在一起的,每一个SqlSession都拥有一个新的Executor对象,由Configuration创建。
StatementHandler(相当于sql语句执行的对象由Executor来调用)
StatementHandler 对象是在 SqlSession 对象接收到命令操作时,由 Configuration 对象中的newStatementHandler 负责调用的,也就是说 Configuration 中的 newStatementHandler 是由执行器中的查询、更新(插入、更新、删除)方法来提供的,StatementHandler 其实就是由 Executor 负责管理和创建的。
ParamenterHandler :(输入映射)
拦截参数的处理。
ResultSetHandler :(输出映射)
拦截结果集的处理。

2.mybatis的插件原理
引入插件的两个方式:
1.在mybatis 全局配置中去配置插件配置
<!--
plugins在配置文件中的位置必须符合要求,否则会报错,顺序如下: properties?, settings?, typeAliases?, typeHandlers?, objectFactory?,objectWrapperFactory?, plugins?, environments?, databaseIdProvider?, mappers?
-->
<plugins>
<!-- com.github.pagehelper为PageHelper类所在包名 -->
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<!-- 使用下面的方式配置参数,后面会有所有的参数介绍 -->
<property name="param1" value="value1"/>
</plugin>
</plugins>
2.在spring配置文件中去整合插件配置
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 注意其他配置 -->
<property name="plugins">
<array>
<bean class="com.github.pagehelper.PageInterceptor">
<property name="properties">
<!--使用下面的方式配置参数,一行配置一个 -->
<value>
xxxxInterceptor
</value>
</property>
</bean> </array>
</property>
</bean>
插件原理:
四大对象创建后不是直接返回而是
1.调用interceptorChain.pluginAll(parameterHandler);
2.从1中获取到所有的拦截器interceptor(插件所需要实现的接口)
3.调用interceptor.plugin(target)返回所有target包装后的对象
public Object pluginAll(Object target){
for(Interceptor interceptor:interceptors){
target=interceptor.plugin(target);
}
return target;
}
注意:
也就是说创建核心四大对象时我们回去调用pluginAll方法来得到所有的拦截器,插件就是利用了拦截器原理。
想要做一个插件我们需要继承Intercepter接口并且重写里面的方法,如下这是我们创建的一个简单插件,注意注释信息
/*
* 完成插件的签名:
* 告诉mybatis插件拦击哪个对象的哪个的方法的哪个参数的签名
*/ @Intercepts({
@Signature(type=StatementHandler.class,method="parameterize",args= java.sql.Statement.class) })
public class MyFirstPlugin implements Interceptor { /*intercept()
* 用来;拦截目标对象的目标方法的执行
*
*/
@Override
public Object intercept(Invocation invocation) throws Throwable {
/*
* 打印拦截的方法:
* 四大对象创建时都会执行插件的拦截方法
* Executor
* ParameterHandler
* ResultMapHandler
*/
System.out.println("MyFirstPlugin=====这个方法被拦截"+invocation.getMethod());
//执行目标方法 (这个方法一定要像小心编写,因为这个会触碰mybatis的底层代码) Object proceed = invocation.proceed();
//返回执行后的返回值
return proceed;
} /*
* plugin()
*包装目标对象,包装目标:给目标对象创建一个代理对象
*/
@Override
public Object plugin(Object target) {
System.out.println("MyFirstPlugin====这些对象已经被创建"+target);
//给目标对象生成一个代理对象
Object wrap=Plugin.wrap(target, this);
//返回为当前target返回的动态代理
return wrap;
}
/*setProperties()
* 将插件注册时的property传递进来
*
*/
@Override
public void setProperties(Properties properties) { System.out.println(properties);
} }
@Intercepts({
@Signature(type=StatementHandler.class,method="parameterize",args= java.sql.Statement.class)
})
告诉mybatis插件拦击哪个对象的哪个的方法的哪个参数的签名
intercept:当四大对象被创建时会拦截对象
而
Object proceed = invocation.proceed();
这个方法是用来指定让那些对象通过的
plugin:这个方法是用来生成代理类,上面的前面指定着哪个对象要被拦截,并且是指定到方法,生成代理类对象,返回相当于是将功能增强了(著名的插件pagehelper就是这个原理)
setProperties:是在配置插件的时候配置指定的参数用来获取参数的
写完拦截器后我们需要在mybatis全局配置文件中配置,或者是在spring中配置配置好后就可以使用
这里我们在mybatis全局配置文件中配置
<plugins>
<plugin interceptor="com.atguigu.plugin.myplugin.MyFirstPlugin">
<property name="username" value="root"/>
<property name="password" value="1234"/>
</plugin>
</plugins>
测试:
@Before
public void setUp() throws Exception {
//1.给出全局配置文件的文件路径
String resource="SqlMapConfig.xml";
//2.读取文件返回一个输入流
InputStream inputStream= Resources.getResourceAsStream(resource);
sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream); } @Test
public void testFindUserById() {
//1.创建sqlSession会话
SqlSession sqlSession = sqlSessionFactory.openSession();
//2.使用Mapper代理的方式创建接口实例(这个实例不是我们创建的而是由MyBatis创建的我们遵守规范即可)
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//3.调用实例方法得到封装好的对象
User user =userMapper.findUserById(1);
System.out.println(user);
sqlSession.close();
}
}
现象:

创建四大对象时必须经过的方法

拦截的对象

3.mybatis的批量操作
如果我们不去配置批量的SqlSession的话,当我们执行下面添加代码时性能就会低很多
我们用时间戳去记录花费了63秒,这个是没有配置批量操作的SqlSession对象
for (int i = 0; i < 1000; i++) {//花费了63秒这与cpu性能有关
String u=UUID.randomUUID().toString();
String uuid=u.substring(0, 5);
employeeMapper.insert(new Employee(null,uuid,"1",uuid+"@qq.com",1));
}
我们去spring整合mybatis时我们是直接将接口、映射文件还用全局配置文件全都配置好了所以我们拿出来的mapper对象是执行不了批量操作的
配置批量的SqlSession对象有两种方式,一种是mybatis自己的方式 一种是整合在spring中的方式
在mybatis中指定批量执行器
private SqlSessionFactory sqlSessionFactory;
@Before
public void setUp() throws Exception {
//1.给出全局配置文件的文件路径
String resource="SqlMapConfig.xml";
//2.读取文件返回一个输入流
InputStream inputStream= Resources.getResourceAsStream(resource);
sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream); } @Test
public void testFindUserById() {
//1.创建sqlSession会话
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
............
注意标红的代码:
ExecutorType这是一个枚举类,里面有许多类型的执行器,我选择
ExecutorType.BATCH也就是我们选择了一个批量操作的执行器,这样我们SqlSession对象就是一个可以批量操作的对象 对比代码:我们这个时候使用批量的SqlSession就是一个性能高的操作花费了55秒
EmployeeMapper emapper= sqlSession.getMapper(EmployeeMapper.class);
for (int i = 0; i < 10; i++) {//花费了55秒
String u=UUID.randomUUID().toString();
String uuid=u.substring(0, 5);
emapper.insert(new Employee(null,uuid,"1",uuid+"@qq.com",1));
}
long end =System.currentTimeMillis();
System.out.println("本次操作花了:"+(end-start)+"毫秒");
在spring整合中配置一个能执行批量操作的执行器
<!-- 创建一个可以批量操作的sqSession -->
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"/>
<constructor-arg name="executorType" value="BATCH"></constructor-arg>
</bean>
注意在:sqlSession类中有一个executorType我们直接给他指定一个BATCH的值这样就是一个批量的执行器
我们可以直接注入就行
代码实例
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations= {"classpath:applicationContext.xml"})
public class Spring4Junit {
private ApplicationContext applicationContext;
@Autowired
private EmployeeMapper employeeMapper; @Autowired
private SqlSession sqlSession; @Test//使用spring的单元测试
public void test02() {
EmployeeMapper emapper= sqlSession.getMapper(EmployeeMapper.class);
for (int i = 0; i < 10; i++) {//花费了55秒
String u=UUID.randomUUID().toString();
String uuid=u.substring(0, 5);
emapper.insert(new Employee(null,uuid,"1",uuid+"@qq.com",1));
}
long end =System.currentTimeMillis();
System.out.println("本次操作花了:"+(end-start)+"毫秒");
} }
@Autowired根据bean的类型注入和@Resource(jdk提供的注解)作用一样但是@Resource是默认按照属性Bean实例名称进行装配
思考?为什么我们没有在spring中配置 employeeMapper对象但是还是能注入,因为这个对象是代理生成的我们将接口映射文件传入他就会代理生成指定的实现类
mybatis第二天02的更多相关文章
- mybatis第一天02
mybatis第二天02 1.映射文件之输入输出映射 1.1映射文件之输入映射类型(parameterType) 1.1.1简单类型 当parameterType为简单类型时,我们只需要直接填写“in ...
- Mybatis第二天(其他)
Mybatis第二天 框架课程 课程计划 动态sql If标签 Where标签 Sql片段 Foreach标签 关联查询 一对一关联 一对多关联 Mybatis整合spring 如何整合spring ...
- Mybatis第二天
Mybatis第二天 框架课程 1. 课程计划 1.输入映射和输出映射 a) 输入参数映射 b) 返回值映射 2.动态sql a) If标签 b) Where标签 c) Sql片段 d) Fore ...
- mybatis第二天01
MyBatis第二天01 1.高级结果映射 1.1根据视频案例,分析表之间的关系 数据模型分析 1. 明确每张表存储的信息 2. 明确每张表中关键字段(主键.外键.非空) 3. 明确数据库中表与表之间 ...
- 第二周02:Fusion ICP逐帧融合
本周主要任务02:Fusion 使用ICP进行逐帧融合 任务时间: 2014年9月8日-2014年9月14日 任务完成情况: 已实现将各帧融合到统一的第一帧所定义的摄像机坐标系下,但是由于部分帧之间的 ...
- 持久层之 MyBatis: 第二篇 :动态SQL And多表查询
MyBatis入门到精通 完整CRUD UserDaoImpl 编写UserDao对应的UserDaoMapper.xml 添加UserDao的测试用例 编写UserDao的测试用例 解决数据库字段名 ...
- Mybatis第二篇【CRUD、分页】
完成CRUD操作 我们在上一篇中已经简单知道了Mybatis是怎么使用的以及工作流程了,这次我们使用Mybatis来完成CRUD的操作,再次巩固Mybatis的开发步骤以及一些细节 包与类之间的结构 ...
- JAVAEE——Mybatis第二天:输入和输出映射、动态sql、关联查询、Mybatis整合spring、Mybatis逆向工程
1. 学习计划 1.输入映射和输出映射 a) 输入参数映射 b) 返回值映射 2.动态sql a) If标签 b) Where标签 c) Sql片段 d) Foreach标签 3.关联查询 a) 一对 ...
- mybatis第二天_拓展——与spring整合以及逆向工程
一.整合思路 1.SqlSessionFactory对象应该放到spring容器中作为单例存在. 2.传统dao的开发方式中,应该从spring容器中获得sqlsession对象. 3.Mapper代 ...
随机推荐
- 2020牛客寒假算法基础集训营4 C : 子段乘积
C:子段乘积 考察点 : 线段树,尺取,乘法逆元 坑点 : 区间要做到不重不漏, long long 侃侃 : 这道题在比赛是写的尺取,但是写了半天发现不好处理除 0 问题(浮点错误),需要用到乘法逆 ...
- 编程语言的实现,从AST(抽象语法树)开始
学习博客:https://baijiahao.baidu.com/s?id=1626159656211187310&wfr=spider&for=pc
- 深浅COPY浅谈
通俗地谈一下深浅COPY的区别,顺便做个笔记.(纯手打,如有不对之处还望大牛指导改正.) 个人觉得区分这个概念需要从数据类型来切入: 1.如果“被复制对象”(后面简称“原对象”)的数据类型为不可变数据 ...
- Date() 按条件打印当前日期的月份和周
条件:打印 月份-第几周 若本月前七天不在全在第一周则这一周计入到上月第五周. 分析: 1.条件判断分别处理前七天和大于等于七天的数据: 2.当前月的7号是关键,如果在周天就不需要放到上月,如果不在周 ...
- MYSQLl给用户授予数据库表权限
给targetUserName用户授予databaseName单个数据库权限 grant all privileges on databaseName.* to targetUserName@&quo ...
- k8s CNI插件简单了解
Kubernetes网络模型本身对某些特定的网络功能有一定要求,但在实现方面也具有一定的灵活性.业界已经有不少不同的网络方案,来满足特定的环境和要求. CNI(container network in ...
- ELK学习002:Elasticsearch 7.x 的安装及配置
Elasticsearch 的安装与启动 1.1 下载 Elasticsearch 7.6.0 下载地址:https://www.elastic.co/cn/downloads/elasticsear ...
- 小白的linux笔记1:CentOS 8 安装与设置
为了在服务器上跑爬虫,以及学SegNet,研究了一圈看来linux是必学品了.在自己电脑上安装了一个 1.官网下载iso,一个linux dvd是稳定版,选之,另一个stream版是更新更快的测试版, ...
- 你没有见过的【高恪】船新版本(SX3000 NAT1 X86魔改)
最近魔改了高恪SX3000 X86,做了如下更改: 开启了SSH 集成了插件(酸酸乳.V2RXY.SMB等等) 开启了NAT1 DIY了主题 精简了官方内置的无用应用和模块 截图(建议右击图片,在新标 ...
- Premiere Pro CC2018安装教程
Premiere Pro CC2018安装教程 下载安装包:去官网下载或者百度PR2018的安装包 解压安装包后,找到Set-up.exe,右键,打开 安装的时候我们需要注册一个账号,点击“获取Ado ...