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的更多相关文章

  1. mybatis第一天02

    mybatis第二天02 1.映射文件之输入输出映射 1.1映射文件之输入映射类型(parameterType) 1.1.1简单类型 当parameterType为简单类型时,我们只需要直接填写“in ...

  2. Mybatis第二天(其他)

    Mybatis第二天 框架课程 课程计划 动态sql If标签 Where标签 Sql片段 Foreach标签 关联查询 一对一关联 一对多关联 Mybatis整合spring 如何整合spring ...

  3. Mybatis第二天

    Mybatis第二天   框架课程 1. 课程计划 1.输入映射和输出映射 a) 输入参数映射 b) 返回值映射 2.动态sql a) If标签 b) Where标签 c) Sql片段 d) Fore ...

  4. mybatis第二天01

    MyBatis第二天01 1.高级结果映射 1.1根据视频案例,分析表之间的关系 数据模型分析 1. 明确每张表存储的信息 2. 明确每张表中关键字段(主键.外键.非空) 3. 明确数据库中表与表之间 ...

  5. 第二周02:Fusion ICP逐帧融合

    本周主要任务02:Fusion 使用ICP进行逐帧融合 任务时间: 2014年9月8日-2014年9月14日 任务完成情况: 已实现将各帧融合到统一的第一帧所定义的摄像机坐标系下,但是由于部分帧之间的 ...

  6. 持久层之 MyBatis: 第二篇 :动态SQL And多表查询

    MyBatis入门到精通 完整CRUD UserDaoImpl 编写UserDao对应的UserDaoMapper.xml 添加UserDao的测试用例 编写UserDao的测试用例 解决数据库字段名 ...

  7. Mybatis第二篇【CRUD、分页】

    完成CRUD操作 我们在上一篇中已经简单知道了Mybatis是怎么使用的以及工作流程了,这次我们使用Mybatis来完成CRUD的操作,再次巩固Mybatis的开发步骤以及一些细节 包与类之间的结构 ...

  8. JAVAEE——Mybatis第二天:输入和输出映射、动态sql、关联查询、Mybatis整合spring、Mybatis逆向工程

    1. 学习计划 1.输入映射和输出映射 a) 输入参数映射 b) 返回值映射 2.动态sql a) If标签 b) Where标签 c) Sql片段 d) Foreach标签 3.关联查询 a) 一对 ...

  9. mybatis第二天_拓展——与spring整合以及逆向工程

    一.整合思路 1.SqlSessionFactory对象应该放到spring容器中作为单例存在. 2.传统dao的开发方式中,应该从spring容器中获得sqlsession对象. 3.Mapper代 ...

随机推荐

  1. 使用Python打造一款间谍程序

    知识点 这次我们使用python来打造一款间谍程序 程序中会用到许多知识点,大致分为四块 win32API  此处可以在MSDN上查看 Python基础重点在cpytes库的使用,使用方法请点击此处 ...

  2. java架构之路-(微服务专题)feign的基本使用和nacos的配置中心

    上次回归: 上次我们说了ribbon的基本使用,包括里面的内部算法,算法的细粒度配置,还有我们自己如何实现我们自己的算法,主要还是一些基本使用的知识,还不会使用ribbon的小伙伴可以回去看一下上一篇 ...

  3. CentOS7 Cloudera Manager6 完全离线安装 CDH6 集群

    本文是在CentOS7.4 下进行CDH6集群的完全离线部署.CDH5集群与CDH6集群的部署区别比较大. 说明:本文内容所有操作都是在root用户下进行的. 文件下载 首先一些安装CDH6集群的必须 ...

  4. gcc, ld

    GCC gcc除了具备基本的c文件编译功能外,还把其它工具的功能也集成了进来,比如as的汇编功能,ld的链接功能. 因此,gcc也可以通过-Wa, option,将option传给汇编器as:也可以通 ...

  5. Django (一) 基础

    创建项目 创建app     python manager.py startapp app01 修改.添加url from django.conf.urls import url,include fr ...

  6. firewall-cmd命令

    firewalld 基本操作 安装firewalld # yum install firewalld firewall-config firewalld启动,停止,开机启动与否,查看状态 # syst ...

  7. 一条Sql的Spark之旅

    背景 ​ SQL作为一门标准的.通用的.简单的DSL,在大数据分析中有着越来越重要的地位;Spark在批处理引擎领域当前也是处于绝对的地位,而Spark2.0中的SparkSQL也支持ANSI-SQL ...

  8. typescript 点滴

    1 extend的用法 const x = extend({ a: 'hello' }, { b: 42 }); 2只有在d.ts,你才可以使用  export as 这样子的语法.而且必须有name ...

  9. Solr系列2-Solr服务安装

    1: Solr简介 1.1 简介: 1.2 下载: 2:Solr 安装 2.1 安装 2.2 目录结构 3 :启动Solr 3.1 启动 3.2使用Solr提供的测试数据 3.5 Solr配置文集 3 ...

  10. 前端vue开发中的跨域问题解决,以及nginx上线部署。(vue devServer与nginx)

    前言 最近做的一个项目中使用了vue+springboot的前后端分离模式 在前端开发的的时候,使用vue cli3的devServer来解决跨域问题 上线部署则是用的nginx反向代理至后台服务所开 ...