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. 记一次IE浏览器做图片预览的坑

    随便写写吧,被坑死了 IE 10 及 IE10以上,可以使用FileReader的方式,来做图片预览,加载本地图片显示 IE 9 8 7 没有FileReader这个对象,所以只能使用微软自己的东西来 ...

  2. 基于MR实现ngram语言模型

    在大数据的今天,世界上任何一台单机都无法处理大数据,无论cpu的计算能力或者内存的容量.必须采用分布式来实现多台单机的资源整合,来进行任务的处理,包括离线的批处理和在线的实时处理. 鉴于上次开会讲了语 ...

  3. Danganronpa 水题。

    Danganronpa Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total ...

  4. webapi使用jwt做权限验证

    考虑到很多公司目前并没有切换到.netcore,所有本文尝试使用.netframework下的webapi 首先使用Nuget 安装 jwt包 安装完成后,创建 jwt的帮助类 public clas ...

  5. jQuery-Moblie在Chrome下出现的问题

    第一次用jQuery然后就遇到很蛋疼的地方,打开页面一直处在菊花状态,一开始以为自己搞错什么,是不是引用错文件,看里面的错误警告 Failed to execute 'replaceState' on ...

  6. 二次开发的Selenium Demo版本

    文件名你们自己命名就好,至于为什么要重写强制位移的函数呢,是因为Mac上Selenium不支持拖拽,只能这样做了,4个文件--------------------------------------- ...

  7. 05.JS函数

    前言: 学习一门编程语言的基本步骤(01)了解背景知识(02)搭建开发环境(03)语法规范(04)常量和变量(05)数据类型(06)数据类型转换(07)运算符(08)逻辑结构(09)函数9.函数——f ...

  8. maven导入sqlserver驱动jar包依赖包到本地仓库

    maven导入sqlserver驱动jar包依赖包到本地仓库 maven项目使用sqlserver的依赖,先下载一个sqlserver的驱动,网址:https://www.microsoft.com/ ...

  9. 【mysql】索引相关的个人总结

    重点参考: MySQL索引原理及慢查询优化 (美团技术分享网站):原理.示例优化都写的很好. 索引很难么?带你从头到尾捋一遍MySQL索引结构,不信你学不会!:原理写的很好. [从入门到入土]令人脱发 ...

  10. 常量, char[], const char[], char*, const char*, char* const以及const char* const的详解

    注意,这里用char类型只是举了一个例子,其他的int之类的也通用. 1: 常量: 例子: char str[] = "Hello world!"; char ch = 'a'; ...