14 道 MyBatis 面试题总结,看完你还敢说懂 MyBatis 吗?
Dao 接口,就是人们常说的 Mapper 接口,接口的全限名,就是映射文件中的 namespace 的值,接口的方法名,就是映射文件中 MappedStatement 的 id 值,接口方法内的参数,就是传递给 sql 的参数。Mapper 接口是没有实现类的,当调用接口方法时,接口全限名+方法名拼接字符串作为 key 值,可唯一定位一个 MappedStatement。
Dao 接口里的方法,是不能重载的,因为是全限名+方法名的保存和寻找策略。
Dao 接口的工作原理是 JDK 动态代理,MyBatis 运行时会使用 JDK 动态代理为 Dao 接口生成代理 proxy 独享,代理对象 proxy 会拦截接口方法,转而执行 MappedStatement 所代表的 sql,然后将 sql 执行结果返回。
4.Mybatis 是如何进行分页的?分页插件的原理是什么?
=============================
1.Mybatis 使用 RowBounds 对象进行分页,它是针对 ResultSet 结果集执行的内存分离,而非物理分页;
RowBounds 分页(不使用 SQL),不再使用 SQL 实现分页
接口
List <User> getUserByRowBound();
mapper.xml
测试
2.直接在 sql 内直接书写 limit 进行分页;
使用 Limit 分页
Select * from user limit 2;#[0,n]
【0,2】出来的时候第一个和第二个。所以 0 代表的第一个。
3.使用分页插件来完成物理分页。
5.Mybatis 动态 sql 是做什么?都有哪些动态 sql?能简述一下动态 sql 的执行原理不?
==============================================
Mybatis 动态 sql 可以让我们在 xml 映射文件内,以标签的形式编写动态 sql,完成逻辑判断和动态拼接 sql 的功能,Mybatis 提供了 9 种动态 sql 标签
其执行原理为,使用 OGNL 从 sql 参数对象中计算表达式的值,根据表达式的值动态拼接 sql,以此来完成动态 sql 的功能。
6.Mybatis 是如何将 sql 执行结果封装为目标对象并返回的?都有那些映射形式?
=========================================
第一种是用<resultMap>标签,逐一定义列明和对象属性名之间的映射关系。
第二种是使用 sql 列的别名功能,将列名书写为对象属性名。
有了列名和属性名的映射关系后,Mybatis 通过反射创建对象,同时使用反射给对象的属性逐一赋值并返回,那些找不到映射关系的属性,是无法完成赋值的。
7.Mybatis 能执行一对一、一对多的关联查询吗?都有那些实现方式,以及他们之间的区别?
=============================================
Mybatis 不仅可以执行一对一、一对多的关联查询,还可以执行多对一,多对多的关联查询,多对一查询,其实就是一对一查询,只需要把 selectOne()修改为 selectList()即可;多对多查询,其实就是一对多查询,只需要把 selectOne()修改为 selectList()即可。
关联对象查询,有两种方式:
一种是单独发送一个 sql 去查询关联对象 resultMap,赋给主对象,然后返回主对象;
按照查询嵌套处理(子查询)
另一种是使用嵌套查询,嵌套查询的含义为使用 join 查询,一部分列是 A 对象的属性值,另外一部分是关联对象 B 的属性值,好处是只发一个 sql 查询,就可以把主对象和其关联对象查出来。
按照查询嵌套处理(联表查询)
8.Mybatis 是否支持延迟加载?如果支持,它的实现原理是什么?
=================================
Mybatis 仅支持 association 关联对象和 collection 关联集合对象的延迟加载,association 指的是一对一,collection 值的就是一对多查询。在 Mybatis 配置文件中,可以配置是否启用延迟加载 lazyLoadingEnabled=truefalse。
它的原理是,使用 CGLIB 创建目标的代理对象,当调用目标方法时,进入拦截器方法,比如调用 a.getB.getName(),拦截器 invoke()方法 a.getB()是 null 值,那么就会单独发送事先保存好的查询关联 B 对象的 sql,把 B 查询上来,然后调用 a.setB(b),于是 a 的对象 b 属性就有值了,接着完成 a.getB().getName()方法的调用。这就是延迟加载的基本原理。
9.Mybatis 的 XML 映射文件中,不同的 XML 映射文件,id 是否可以重复?
========================
===============
不同的 XML 映射文件,如果配置了 Namespace,那么 Id 可以重复;如果没有配置 namespace,那么 Id 不能重复;毕竟 Namespace 不是必须加的,只是最佳实践而已。
原因就是 namespace+id 是 Map<String.MappedStatement>的 key 使用的,如果没有 Namespace,就剩下 Id,那么 id 重复会导致数据互相覆盖。有了 namespace,自然 id 就可以重复,namespcae 不同,namespace+id 自然也就不同。
10.Mybatis 都有哪些 Executor 执行器?他们之间的区别是什么?
=====================================
有三种:SimpleExecutor、ReuseExector、BatchExector。
评论