WEB框架之MyBatis分析

1.常用核心原理


1.1ORM框架:

  • 也就是把表字段映射为对象的属性;包含hibreate功能,可以直接写sql语句,进行表到字段的映射;

1.2ORM框架之前:

  • 1、导入JDBC依赖包  
  • 2、通过DriverManager注册驱动 
  • 3、创建连接  
  • 4、创建Statement
  • 5、执行CRUD  
  • 6、操作结果集(需要手动设置到对象) 
  • 7、关闭连接
//jdbc使用预编译语句
String sqlString ="insert into user(id, password, name, email, address) values(?, ?, ?, ?, ?)";  
PreparedStatement pstmt = connection.PreparedStatement(sqlString);  
pstmt.setString(1, user.id);  
pstmt.setString(2, user.password);  
pstmt.setString(3, user.name);  
pstmt.setString(4, user.email);  
pstmt.setString(5, user.address);  

1.3接口+注解 / xml文件:

  • sql解析 / 解析抽象语法树都是一堆if/else判断解析出一个个节点  或者 使用监听者模式利用回调来进行实现

1.4架构设计

  • 配置中心(SqlSessionFactoryBuilder包含多种注册中心进行缓存)
  • SqlSession(包含执行器)
  • 多种执行器(获取代理类执行invoke方法)
  • 字段映射(ParameterHandler
  • 结果集映射(ResultSetHandler

1.5读源码

  • 架构设计-----打开官网找入口点
//1.从配置文件(通常是xml配置文件中)得到sessionFactory。
String resources = "mybatis.xml";
//获取InputStreamReadIo
//mybatis对我们操作流做了一个封装,对用户来说比较简单使用
Reader reader = Resources.getResourceAsReader(resources);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
try (SqlSession session = sqlSessionFactory.openSession()) {
    BlogMapper mapper = session.getMapper(BlogMapper.class);
    Blog blog = mapper.selectBlog(101);
}

2.Mapper


2.1注册Mapper

  • 原本使用hashmap+单线程注册(缓存起来)
  • 改进:针对大数据量可以改为使用ConcurrentHashMap(尽量避免扩容带来额外开销)+多线程并发注册

2.2解析XML

  • XML解析(DOM4j)---使用Xpath查找节点(生成XNode节点对应标签)
  • @一种是基于DOM解析为树形结构对象(比如Xpath解析),加载整个结构到内存,比如JDOM,DOM4j;
  • @一种是基于SAX的事件驱动解析(比如Digester解析),加载部分结构比较节省内存;
  • 将mapper.class接口 和 对应的代理类进行映射,注册到mapperRegistry
  • 将解析出的所有xml信息,将接口的一个method 和 具体对应的元信息进行绑定形成MappedStatement,并进行注册到mappedStatements
  • mappedStatements和mapperRegistry都存在Configuration类里,所有的缓存配置都在此配置中心

3.执行流程


3.1Mapper接口实例生成以及执行

  • 从sqlSession.getMapper获取mapper接口类,是通过MapperProxyFactory创建出动态代理的实例
  • invoke方法会先从缓存中获取方法,然后会进行执行,
  • 通过sqlsession进行执行,sqlsession包含executor,所以实际还是由执行器executor进行执行;

ps:实际执行之前,先要判断一级缓存才会进行实际的query(该缓存需要参数、sql语句等全部一致才可以),在进行更新的时候会清除所有缓存,防止脏数据,二级缓存需要进行设置才可以使用;

3.2核心执行器

  • Executor(接口)---BaseExecutor(抽象类)----实现类
  • 模板方法(模式)--接口定义方法,抽象类将不变的写成算法实现、将变化的写成抽象方法,最后扔给实现类进行实现
  • 装饰者(模式)----针对原有exector的方法进行装饰

三种执行器:

  • ExecutorType.SIMPLE   它只为每个语句执行的时候都会创建一个PreparedStatement(默认的执行器)。
  • ExecutorType.REUSE    只对预编译好的sql语句进行缓存参数值可以不同的,可以重复使用PreparedStatements。
  • ExecutorType.BATCH    可以批量进行更新,但不支持select。
  • CachingExecutor 利用了二级缓存,mapper表级别的缓存,使用cacheEnabled配置,会先判断二级缓存然后才会判断一级缓存。 

3.3执行器执行

  • 优先需要判断一级缓存,如果没有才会执行真正的查询
  • 编译sql语句,设置参数值
  • 进行实际的查询并且返回结果
  • ResultSetHandler进行结果集映射
  • 完成之后,逐层关闭i/o流直到回溯到执行器Executor(关闭resultSet--statement--connection)

 

  • 扩展:一级缓存;
  • 在同个SqlSession中,查询语句相同的sql会被缓存,但是一旦执行新增或更新或删除操作,缓存就会被清除;
  • 只需要在一个事务中,不需要commit,两次相同的查询实际只会查一次数据库;
  • 扩展:二级缓存;
  • SqlSession commit或close之后,二级缓存才会生效;
  • 因为在commit的时候会从entriesToAddOnCommit这个map结构获取元素然后放入实际的缓存map中,核心就是先用了一个map进行了一个临时的存储

4.插件原理


4.1责任链模式

  • 两种形式:一种带拦截,一种不带拦截(Mybatis)

4.2拦截器原理

  • 原理介绍:
  • 责任链模式---通过拦截器对StatementHandler、ParameterHandler和ResultSetHandler这三种类型的handel处理器进行拦截来实现不同功能;
  •  
  • 调用体系:
  • Configuration#newParameterHandler/newResultSetHandler/newStatementHandler
  • InterceptorChain#pluginAll(使用了责任链模式增强)
  • Interceptor(接口)#plugin   生成对应handler处理器的代理类
  • 通过对原handler接口的方法通过动态代理进行增强;
  •  
  • 扩展:可以不使用原生提供的动态代理去做,可以直接在plugin 方法里通过类型判断进行实现;
  •  
  • 扩展:分页机制如何实现;
  • 实现Interceptor(接口),核心就是对sql进行改写(https://blog.csdn.net/feinifi/article/details/88769101);
  • 查出来全部数据,只返回部分数据即可;
  • 直接头通过limit进行控制;
  • 扩展:超大分页如何优化;
  • 可以使用覆盖索引优化;
  • 如果id是连续的,可以直接索引id大于1w的;
  • 可以使用redis存储每页的数据;

5.Mybatis与Spring整合


5.1整合

  • 扫描所有mapper接口,在xxxServiceImpl里进行依赖注入@Autowired
  • 将dataSource、configLocation、mapperLocations(扫描所有xml文件)配置到sqlSessionFactory中
  • 最终,配置transactionManager以及dataSource以便被其他bean注入

5.2SpringBean实例创建过程

  • AbstractApplicationContext的refresh方法代表了bean的生命周期(从注册到实例化
  • 进行实例化
  • 初始化实例:xxxAware进行设置属性properties---初始化之前的后置处理器---初始化bean(InitializingBean的
    afterPropertiesSet方法)---用户定义的初始化方法---初始化之后的后置处理器
  • 将初始化好的单实例会缓存起来 :如果要获取FactoryBean实例就要在beanname前加&,如果获取FactoryBean创建出来的对象不要加&即可
  • 生命结束先执行DisposableBean的destory接口,在执行用户自定义的destory-method方法
  • 至此整个生命周期结束

5.3Spring的类型转换器

  • TypeConverter接口----TypeConverterSupper进行实现--(装饰者模式)--委派给TypeConverterDelegate进行实现---先使用PropertyEditor,如果没有可以使用ConversionService(可以自定义converter可扩展性强)进行实现
  • 要增加一个类型转换器就可以增加一个自定义的converter

5.4获取mapper接口的两种方式

  • SpringBoot注解配置:使用@MapperScan可以指定要扫描的Mapper类的包的路径,底层通过MapperScannerRegistrar类进行实现ImportBeanDefinitionRegistrar接口注册BD;
  • 先注册beanDefinitions,在进行设置beanDefinitions,
  • xml配置:配置MapperScannerConfigurer类即可,底层通过ClassPathBeanDefinitionScanner类实现,
  • 先设置beanDefinitions,在进行注册beanDefinitions
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值