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. Entity Framework 实体状态

    从今天开始我们开始讲解EF中的实体状态和数据操作,这篇文章先讲解实体状态. 我们通过前面的学习,知道EF通过上下位负责跟踪实体的状态,实体状态的位置是在命名空间 System.Dat.Entity 里 ...

  2. Gorm与数据库(单复数)表结构之间的映射

    Gorm连接MySQL: import ( _ "github.com/go-sql-driver/mysql" "github.com/jinzhu/gorm" ...

  3. 二维数组转稀疏数组、稀疏数组恢复二维数组(Java实现)

    public static void main(String[] args) { // 创建一个原始的二维数组 9*9 int chessArr1[][] = new int[9][9]; // 0表 ...

  4. JVM性能优化系列-(4) 编写高效Java程序

    4. 编写高效Java程序 4.1 面向对象 构造器参数太多怎么办? 正常情况下,如果构造器参数过多,可能会考虑重写多个不同参数的构造函数,如下面的例子所示: public class FoodNor ...

  5. 使用chrome控制台调试js代码

    1.打开控制台(空白页签即可) 2.将控制台在独立页打开(点击控制台右上角的三个点图标,然后点击如下图中的图标) 3.创建脚本编辑页面 4.页面区域说明 5.花键+回车之行代码 6.常用命令介绍 6. ...

  6. PgSQL备份

    SQL转储. 这里我们用到的工具是pg_dump和pg_dumpall. 这种方式可以在数据库正在使用的时候进行完整一致的备份,并不阻塞其它用户对数据库的访问.它会产生一个脚本文件,里面包含备份开始时 ...

  7. Nginx-2.初学者使用

    原文 Nginx有一个master进程和几个worker进程.master进程用来读取和评估配置文件,以及维护worker进程.worker进程用来处理实际的请求.Nginx使用事件模型和基于操作系统 ...

  8. axios,vue-echarts, async, vue 图表数据处理; axios 跨域代理; 异步同步请求接口;生命周期函数

    1.vue-echarts 安装和组件引用 插件官网 https://github.com/ecomfe/vue-echarts 安装 npm install eacharts vue-echarts ...

  9. C# 根据天、周、月汇总统计生成统计报表

    先看核心代码: public List<DataEntity> SearchShopSalesReport(DateTimeOffset? dateFrom, DateTimeOffset ...

  10. Windows一些技巧

    更改文件夹的显示名称 在要修改的文件夹下创建desktop.ini,在文件中输入: [.ShellClassInfo] LocalizedResourceName= [要显示的名字] 在CMD中输入命 ...