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代 ...
随机推荐
- error C2338: No Q_OBJECT in the class with the signal (NodeCreator.cpp)
在Qt中,当派生类需要用到信号与槽机制时,有两个要求. 1.该类派生自QObject类. 2.类中有Q_OBJECT宏. 本次报错的原因就是因为没有在类中添加Q_OBJECT宏. 而我的出错原因更傻逼 ...
- 《Head first设计模式》之外观模式
外观模式提供了一个统一的接口,用来访问子系统中的一群接口.外观定义了一个高层接口,让子系统更容易使用. 我们已经知道适配器模式是如何将一个类的接口转换成另一个符合客户期望的接口的.现在我们要看一个改变 ...
- 搭建grafana+telegraf+influxdb服务器性能监控平台
最近在学习性能测试,了解到一套系统资源使用率低的监控环境,也就是grafana+telegraf+influxdb. InfluxDB是一款优秀的时间序列数据库,适合存储设备性能.日志.物联网传感器等 ...
- Kubernetes最新版核心命令
#查看所有namespace的pods运行情况 kubectl get pods --all-namespaces #查看具体pods,记得后边跟namespace名字哦 kubectl get po ...
- 杭电-------2046骨牌铺方格(C语言写)
#include<stdio.h> ] = { }; long long recrusion(int n) { || a[n]>) { return a[n]; } ) + recr ...
- Unity5.5.6 升级到 2018.4.1 打包出现的问题 : Gradle version 2.10 is required. Current version is 5.1.1
起因:最近要在googleplay上架新游戏,而谷歌要求新上架的应用要支持64位,鉴于老版本的unity不支持打包64位apk,所以决定升级unity版本到2018.4.1, 但打包过程中出现了几个问 ...
- mybatis缓存,包含一级缓存与二级缓存,包括ehcache二级缓存
一,引言 首先我们要明白一点,缓存所做的一切都是为了提高性能.明白了这一点下面我们开始进入正题. 二,mybatis缓存概要 ①.mybatis的缓存有两种,分别是一级缓存和二级缓存.两者都属于查询缓 ...
- .NET代码混淆工具NET Reactor - 初学者系列-学习者系列文章
这几天无事,除了看书,然后就倒腾原来的代码.想起.NET的代码混淆工具软件,所以今天就讲讲这个.NET代码混淆工具. .NET代码混淆工具软件,以前有了解和找过,但是当时需求不大,所以找了下就搁置了. ...
- C++泛化动态数组
泛化动态数组 动态数组的核心思想是在存储数据时动态的管理数组元素占用的内存,通过调用动态数组的类方法来对数组中的数据进行增删改查操作.最初我们为数组申请10个元素的空间,放我们不断向数组中添加数据时, ...
- 使用jdbc将mysql数据库中的内容封装为指定对象的list集合
使用jdbc将mysql数据库中的内容封装为指定对象的list集合 public List<User> findAll() { private JdbcTemplate template ...