(1)MyBatis是一个支持普通SQL查询,存储过程和高级映射的优秀持久层框架。
(2)MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索封装。
(3)MyBatis可以使用简单的XML或注解用于配置和原始映射,将接口和Java的POJO(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录。
(1)MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis。iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAO)。
(2)MyBatis是iBatis的升级版,用法有很多的相似之处,但是MyBatis进行了重要的改进。主要表现在以下几个方面:
1)Mybatis实现了接口绑定,使用更加方便。
2)对象关系映射的改进,效率更高
3)MyBatis采用功能强大的基于OGNL的表达式来消除其他元素。
(1)简单易学
mybatis本身就很小且简单。没有任何第三方依赖,最简单安装只要两个jar文件+配置几个sql映射文件易于学习,易于使用,通过文档和源代码,可以比较完全的掌握它的设计思路和实现。
(2)灵活
mybatis不会对应用程序或者数据库的现有设计强加任何影响。 sql写在xml里,便于统一管理和优化。通过sql基本上可以实现我们不使用数据访问框架可以实现的所有功能,或许更多。
(3)解除sql与程序代码的耦合
通过提供DAL层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性。
(4)提供映射标签,支持对象与数据库的orm字段关系映射
(5)提供对象关系映射标签,支持对象关系组建维护
(6)提供xml标签,支持编写动态sql。
(1)编写SQL语句时工作量很大,尤其是字段多、关联表多时,更是如此。
(2)SQL语句依赖于数据库,导致数据库移植性差,不能更换数据库。
(3)框架还是比较简陋,功能尚有缺失,虽然简化了数据绑定代码,但是整个底层数据库查询实际还是要自己写的,工作量也比较大,而且不太容易适应快速数据库修改。
(4)二级缓存机制不佳
(1)mybatis的优点同样是mybatis的缺点,正因为mybatis使用简单,数据的可靠性、完整性的瓶颈便更多依赖于程序员对sql的使用水平上了。sql写在xml里,虽然方便了修改、优化和统一浏览,但可读性很低,调试也非常困难,也非常受限。
(2)mybatis没有hibernate那么强大,但是mybatis最大的优点就是简单小巧易于上手,方便浏览修改sql语句。
功能结构
(1)API接口层:提供给外部使用的接口API,开发人员通过这些本地API来操纵数据库。接口层一接收到调用请求就会调用数据处理层来完成具体的数据处理。
(2)数据处理层:负责具体的SQL查找、SQL解析、SQL执行和执行结果映射处理等。它主要的目的是根据调用的请求完成一次数据库操作。
(3)基础支撑层:负责最基础的功能支撑,包括连接管理、事务管理、配置加载、缓存处理,这些都是共用的东西,将他们抽取出来作为最基础的组件。为上层的数据处理层提供最基础的支撑。
数据处理流程
需要加载配置文件,其中配置文件主要来自于开发者自定义的配置文件或者存在于Java代码中的注解,SQL的配置信息加载成为一个个MappedStatement对象(包括了传入参数映射配置、执行的SQL语句、结果映射配置),存储在内存中。
调用Mybatis提供的API,为指定的SQL ID传入参数对象,然后将请求传递给下层的请求处理层进行处理。
API接口层传递请求过来,为指定的SQL ID传入参数对象,接着会进行如下一系列操作处理:
(1) 根据SQL的ID查找对应的MappedStatement对象。
(2) 根据传入参数对象解析MappedStatement对象,得到最终要执行的SQL和执行传入参数。
(3) 获取数据库连接,根据得到的最终SQL语句和执行传入参数到数据库执行,并得到执行结果。
(4) 根据MappedStatement对象中的结果映射配置对得到的执行结果进行转换处理,并得到最终的处理结果。
(5) 释放连接资源。
将最终的操作处理结果返回给用户请求操作。
操作Session
(1) Mybatis 配置核心
核心配置文件
(2) 功能接口配置
SQL操作配置
(2) 测试
数据操作
在注解上不能直接使用动态的SQL,需要在其前后加入;
对于LIKE 也是不能够直接使用的 可以借助concat函数实现;
(1) 功能接口配置
注解操作
(2) 测试
数据操作
(1)MyBatis会在表示会话的SqlSession对象中建立一个简单的缓存,将每次查询到的结果结果缓存起来,当下次查询的时候,判断先前有个完全一样的查询,会直接从缓存中直接将结果取出,返回给用户,不需要再进行一次数据库查询了。
(2)一个SqlSession对象中创建一个本地缓存(local cache),对于每一次查询,都会尝试根据查询的条件去本地缓存中查找是否在缓存中,如果在缓存中,就直接从缓存中取出,然后返回给用户;否则,从数据库读取数据,将查询结果存入缓存并返回给用户。
(3)由于MyBatis使用SqlSession对象表示一次数据库的会话,那么,对于会话级别的一级缓存也应该是在SqlSession中控制的。
(4)SqlSession只是一个MyBatis对外的接口,SqlSession将它的工作交给了Executor执行器这个角色来完成,负责完成对数据库的各种操作。
(5)当创建了一个SqlSession对象时,MyBatis会为这个SqlSession对象创建一个新的Executor执行器,而缓存信息就被维护在这个Executor执行器中,MyBatis将缓存和对缓存相关的操作封装成了Cache接口中。
(6)Executor接口的实现类BaseExecutor中拥有一个Cache接口的实现类PerpetualCache,则对于BaseExecutor对象而言,它将使用PerpetualCache对象维护缓存。
(7)由于Session级别的一级缓存实际上就是使用PerpetualCache维护的。PerpetualCache实现原理其实很简单,其内部就是通过一个简单的HashMap 来实现的,没有其他的任何限制。
(1)MyBatis在开启一个数据库会话时,会创建一个新的SqlSession对象,SqlSession对象中会有一个新的Executor对象,Executor对象中持有一个新的PerpetualCache对象;当会话结束时,SqlSession对象及其内部的Executor对象还有PerpetualCache对象也一并释放掉。
(2)如果SqlSession调用了close()方法,会释放掉一级缓存PerpetualCache对象,一级缓存将不可用;
(3)如果SqlSession调用了clearCache(),会清空PerpetualCache对象中的数据,但是该对象仍可使用;
(4)SqlSession中执行了任何一个update操作(update()、delete()、insert()),都会清空PerpetualCache对象的数据,但是该对象可以继续使用;
缓存应用流程
(1)MyBatis对会话(Session)级别的一级缓存设计的比较简单,就简单地使用了HashMap来维护,并没有对HashMap的容量和大小进行限制,其主要原因:
1)一般而言SqlSession的生存时间很短。一般情况下使用一个SqlSession对象执行的操作 不会太多,执行完就会消亡;
2)对于某一个SqlSession对象而言,只要执行update操作(update、insert、delete),都 会将这个SqlSession对象中对应的一级缓存清空掉,所以一般情况下不会出现缓存过 大,影响JVM内存空间的问题;
3)可以手动地释放掉SqlSession对象中的缓存。
(2)一级缓存是一个粗粒度的缓存,没有更新缓存和缓存过期的概念,MyBatis的一级缓存就是使用了简单的HashMap,MyBatis只负责将查询数据库的结果存储到缓存中去,不会去判断缓存存放的时间是否过长、是否过期,因此也就没有对缓存的结果进行更新这一说了。
(1)MyBatis的二级缓存是Application级别的缓存,它可以提高对数据库查询的效率,以提高应用的性能。
(2)MyBatis使用了二级缓存,并且Mapper和select语句也配置使用了二级缓存,那么在执行select查询的时候,MyBatis会先从二级缓存中取输入,其次才是一级缓存,即MyBatis查询数据的顺序是:二级缓存———>一级缓存——>数据库。
(1)MyBatis并不是简单地对整个Application就只有一个Cache缓存对象,它将缓存划分的更细,即是Mapper级别的,每一个Mapper都可以拥有一个Cache对象为每一个Mapper分配一个Cache缓存对象(使用节点配置)
(2)MyBatis将Application级别的二级缓存细分到Mapper级别,即对于每一个Mapper.xml,如果在其中使用了节点,则MyBatis会为这个Mapper创建一个Cache缓存对象。
(3)多个Mapper共用一个Cache缓存对象(使用节点配置)节点,来指定你的这个Mapper使用到了哪一个Mapper的Cache缓存。
(4)要想使某条Select查询支持二级缓存,需要保证:
1)MyBatis支持二级缓存的总开关:全局配置变量参数cacheEnabled=true;
2)该select语句所在的Mapper,配置了或节点,并且有效;
3)该select语句的参数useCache=true;
(1)MyBatis对二级缓存的设计非常灵活,它自己内部实现了一系列的Cache缓存实现类,并提供了各种缓存刷新策略如LRU,FIFO等等。
(2)MyBatis还允许用户自定义Cache接口实现,用户是需要实现org.apache.ibatis.cache.Cache接口,然后将Cache实现类配置在节点的type属性上即可;除此之外,MyBatis还支持跟第三方内存缓存库如Memecached的集成,总之,使用MyBatis的二级缓存有三个选择:
1)MyBatis自身提供的缓存实现;
2)用户自定义的Cache接口实现;
3)跟第三方内存缓存库的集成;
(1) Mybatis插件又称拦截器,采用责任链模式,通过动态代理组织多个插件(拦截器),这些插件可以改变Mybatis的默认行为(诸如SQL重写之类的),由于插件会深入到Mybatis的核心,因此在编写自己的插件前最好了解下它的原理,以便写出安全高效的插件。
(2)MyBatis 允许你在已映射语句执行过程中的某一点进行拦截调用。
(3)Mybatis是通过动态代理的方式实现拦截的。
(1)不编写不必要的插件。
(2)实现plugin方法时判断一下目标类型,是本插件要拦截的对象才执行Plugin.wrap方法,否者直接返回目标本省,这样可以减少目标被代理的次数。
(3)所有可能被拦截的处理类都会生成一个代理
(4)处理类代理在执行对应方法时,判断要不要执行插件中的拦截方法
(5)执行插接中的拦截方法后,推进目标的执行
(6)如果有N个插件,就有N个代理,每个代理都要执行上面的逻辑。这里面的层层代理要多次生成动态代理,是比较影响性能的。虽然能指定插件拦截的位置,但这个是在执行方法时动态判断,初始化的时候就是简单的把插件包装到了所有可以拦截的地方。
Mybatis的插件实现要实现 Interceptor 接口,接口的方法主要功能如下:
(1)setProperties方法,在Mybatis进行配置插件的时候可以配置自定义相关属性,即:接口实现对象的参数配置
(2)plugin方法,插件用于封装目标对象的,通过该方法我们可以返回目标对象本身,也可以返回一个它的代理,可以决定是否要进行拦截进而决定要返回一个什么样的目标对象,官方提供了示例:return Plugin.wrap(target, this);
(3)intercept方法,进行拦截的时候要执行的方法
(4)plugin接口,(Executor/ParameterHandler/ResultSetHander/StatementHandler)的代理对象。在调用对应对象的接口的时候,可以进行拦截并处理。返回参数target对象。
MyBatis 知识点
作者:云先生_2017
链接:https://www.jianshu.com/p/4fe280c44294
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。