引言
MyBatis工作原理如下图所示:
1、读取MyBatis配置文件:mybatis-config.xml为MyBatis的全局配置文件,配置了MyBatis的运行环境等信息,例如数据库连接信息。
2、加载映射文件:映射文件即SQL映射文件,该文件配置了操作数据库的SQL语句,需要在MyBatis配置文件mybatis-config.xml中加载。mybatis-config.xml文件可以加载多个映射文件,每个文件对应数据库中的一张表。
3、构造会话工厂:通过MyBatis的环境等配置信息构建会话工厂SqlSessionFactory。
4、创建会话对象:由会话工厂创建SqlSession对象,该对象中包含了执行SQL语句的所有方法。
5、Executor执行器:MyBatis底层定义了一个Executor接口来操作数据库,它将根据SqlSession传递的参数动态地生成需要执行的SQL语句,同时负责查询缓存的维护。
6、MappedStatement对象:在Executor接口的执行方法中有一个MappedStatement类型的参数,该参数是对映射信息的封装,用于存储要映射的SQL语句的id,参数等信息。
7、输入参数映射:输入参数类型可以是Map、List等集合类型,也可以是基本数据类型的POJO类型。输入参数映射过程类似于JDBC对PreparedStatement对象设置参数的过程。
8、输出结果映射:输出结果类型可以是 Map、 List 等集合类型,也可以是基本数据类型和 POJO 类
型。输出结果映射过程类似于 JDBC 对结果集的解析过程。
问题 1 什么是Mybatis?
1、Mybatis是一个半ORM(对象关系映射)框架,它内部封装了JDBC,开发时只需要关注SQL语句本身,不需要花费精力去处理加载驱动、创建连接、创建statement等繁杂的过程。程序员直接编写原生态sql,可以严格控制sql执行性能,灵活度高。
2、MyBatis 可以使用 XML 或注解来配置和映射原生信息,将 POJO映射成数据库中的记录,避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。
3、通过xml 文件或注解的方式将要执行的各种 statement 配置起来,并通过java对象和 statement中
sql的动态参数进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射为java对象并返回。(从执行sql到返回result的过程)。
问题 2 Mybaits的优点?
1、基于SQL语句编程、相当灵活,不会对应用程序或者数据库的现有设计造成任何影响,SQL写在XML里,解除SQL与程序代码的耦合,便于统一管理;提供XML标签,支持编写动态SQL语句,并可重用。
2、与JDBC相比,减少了50%以上的代码量,消除了JDBC大量冗余代码,不需要手动开关连接;
3、很好的与各种数据库兼容(因为MyBatis使用JDBC来连接数据库,所以只要JDBC支持的数据库,MyBatis都支持)。
4、能够与Spring很好的集成;
5、提供映射标签,支持对象与数据库的ORM字段关系映射;提供对象关系映射标签,支持对象关系组件维护。
问题 3 MyBatis框架的缺点
1、SQL语句的编写工作量较大,尤其当字段多、关联表多时,对开发人员编写SQL语句的功底有一定要求。
2、SQL语句依赖于数据库、导致数据库移植性差,不能随便更换数据库。
问题 4 MyBatis框架适用场合
1、MyBatis专注于SQL本身,是一个足够灵活的DAO层解决方案。
2、对性能的要求很高,或者需求变化较多的项目,如互联网项目,MyBatis将是不错的选择。
问题 5 MyBatis与Hibernate有哪些不同?
相同点:都是对JDBC的封装,都是持久层的框架,都用于DAO层的开发;
不同点:
- 映射关系不同:MyBatis是一个半自动映射的框架,配置Java对象与SQL语句执行结果的对应关系,多表关联关系配置简单;Hibernate是一个全表映射的框架,配置Java对象与数据库表的对应关系,多表关联关系配置复杂。
- SQL优化和移植性:Hibernate 对SQL语句封装,提供了日志、缓存、级联(级联比 MyBatis 强大)等特性,此外还提供 HQL(Hibernate Query Language)操作数据库,数据库无关性支持好,但会多消耗性能。如果项目需要支持多种数据库,代码开发量少,但SQL语句优化困难;MyBatis 需要手动编写 SQL,支持动态 SQL、处理列表、动态生成表名、支持存储过程。开发工作量相对大些。直接使用SQL语句操作数据库,不支持数据库无关性,但sql语句优化容易。
问题 6 为什么说Mybatis是半自动ORM映射工具?它与全自动的区别在哪里?
Hibernate属于全自动ORM映射工具,使用Hibernate查询关联对象或者关联集合对象时,可以根
据对象关系模型直接获取,所以它是全自动的。
Mybatis在查询关联对象或关联集合对象时,需要手动编写sql来完成,所以,称之为半自动ORM
映射工具。
问题 8 传统JDBC开发存在什么问题?
- 频繁创建数据库连接对象、释放,容易造成系统资源浪费,影响系统性能。可以使用连接池解决这 个问题。但是使用jdbc需要自己实现连接池。
- sql语句定义、参数设置、结果集处理存在硬编码。实际项目中sql语句变化的可能性较大,一旦发
生变化,需要修改java代码,系统需要重新编译,重新发布。不好维护。 - 使用preparedStatement向占有位符号传参数存在硬编码,因为sql语句的where条件不一定,可
能多也可能少,修改sql还要修改代码,系统不易维护。 - 结果集处理存在重复代码,处理麻烦。如果可以映射成Java对象会比较方便。
问题 9 JDBC编程有哪些不足之处,MyBatis是如何解决的?
1、数据库连接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库连接池可解决此问题。
解决:在mybatis-config.xml中配置数据库连接池,使用连接池管理数据库连接。
2、SQL语句写在代码中造成代码不易维护,实际应用SQL变化的可能较大,SQL变动需要改变Java代码。
解决:将SQL语句配置在XXXMapper.xml文件中与Java代码分离。
3、向SQL语句传参数,因为SQL语句的where条件不一定,可能多也可能少,占位符需要和参数一一对应。
解决:MyBatis自动将Java对象映射至SQL语句。
4、对结果集解析麻烦,SQL变化导致解析代码变化,且解析前需要遍历,如果将数据库记录封装成POJO对象解析比较方便。
解决:MyBatis自动将SQL执行结果映射至Java对象。
问题 10 Mybatis是否支持延迟加载?如果支持,它的实现原理是什么?
Mybatis仅支持association关联对象和collection关联集合对象的延迟加载,association指的就是一对
一,collection指的就是一对多查询。在Mybatis配置文件中,可以配置是否启用延迟加载
lazyLoadingEnabled=true|false。
它的原理是,使用CGLIB创建目标对象的代理对象,当调用目标方法时,进入拦截器方法,比如调用
a.getB().getName(),拦截器invoke()方法发现a.getB()是null值,那么就会单独发送事先保存好的查询关联B对象的sql,把B查询上来,然后调用a.setB(b),于是a的对象b属性就有值了,接着完成
a.getB().getName()方法的调用。这就是延迟加载的基本原理。
当然了,不光是Mybatis,几乎所有的包括Hibernate,支持延迟加载的原理都是一样的。
问题 11 Mybatis的一级、二级缓存
1)一级缓存: 基于 PerpetualCache 的 HashMap 本地缓存,其存储作用域为 Session,当 Session
flush 或 close 之后,该 Session 中的所有 Cache 就将清空,默认打开一级缓存。
2)二级缓存与一级缓存其机制相同,默认也是采用 PerpetualCache,HashMap 存储,不同在于其存
储作用域为 Mapper(Namespace),并且可自定义存储源,如 Ehcache。默认不打开二级缓存,要开启二级缓存,使用二级缓存属性类需要实现Serializable序列化接口(可用来保存对象的状态),可在它的映射文件中配置 ;
3)对于缓存数据更新机制,当某一个作用域(一级缓存 Session/二级缓存Namespaces)的进行了C/U/D操作后,默认该作用域下所有 select 中的缓存将被 clear。
返回面试宝典