Mybatis面试题也是Java面试题经常问到的内容,今天给大家重点分享19道Mybatis面试题及答案@mikechen
1、Mybatis的Mapper接口工作原理是什么?方法能重载吗?
Mapper接口全限定名称对应着Mapper.xml里的namespace。
namespace+id就是sqlSession语句的statement,也就是Map<String, MappedStatement>的key。
方法名和sql的id一致,所以Mapper接口的方法是不能重载的。
Mapper接口工作原理是使用JDK动态代理。SqlSession存在一个getMapper方法。该方法最终会使用Proxy.newProxyInstance方法去构建一个代理对象。代理对象拦截接口方法,从而执行MappedStatement所代表的sql,最终返回结果。
2、Mybatis是如何分页的?分页插件的原理是什么?
Mybatis使用RowBounds对象分页,它是针对ResultSet结果进行内存分页,而非物理分页,可使用分页插件实现物理分页。
分页插件原理是使用mybatis插件机制,实现自定义分页插件。
在插件拦截的方法内执行SQL,然后重写SQL,根据dialect方法,添加对应的物理分页语句和参数。
如mysql重写,select * from user; 拦截重写后:select t.* from (select * from user) t limit 0, 10
3、简述Mybatis插件运行原理,以及如何编写一个插件?
Mybatis仅可以编写针对ParameterHandler,ResultSetHandler,StatementHandler,Executor这四种接口的插件。
插件实现原理是JDK动态代理当时,因为Plugin实现了InvocationHandler接口。重写了invoke方法,其实对应Plugin来说就是一个JDK的代理对象。
每当执行 这四种接口对象的方法时,就会进入invoke方法。这里面会根据注解@Signature标识的类和方法及参数去调用指定的方法。
编写Plugin需要实现Mybatis的Interceptor接口,并实现intercept,plugin,setProperties方法。重写的逻辑在intercept方法中编写。
4、Mybatis执行批量插入,能返回数据库自增ID列表吗?
JDBC都能,Mybatis自然那也能。
5、Mybatis动态SQL是做什么的?都有哪些动态SQL?能简述一下动态SQL的执行原理不?
动态SQL让我们在xml映射文件中,以标签的形式编写动态SQL,完成逻辑判断和SQL拼接。
mybatis提供了9中动态SQL标签if|where|choose|when|otherwise|foreach|set|trim|bind
动态SQL的原理是使用OGNL表达式从SQL参数对象中计算表达式的值,根据值动态拼接SQL
6、Mybatis如何将SQL执行结果封装为目标对象并返回的?都有哪些映射形式?
使用resultMap自定义映射返回,使用resultType+数据库列的别名返回与pojo一致的字段做自动参数绑定。
最终通过反射对返回对象赋值。
7、Mybatis一对一,一对多关联查询有哪些方式实现?有何区别?
一是单独查询关联对象,然后赋值给主对象。< assocation>和< collection>标签分别单独查询一对一和一对多
二是使用join做关联查询。
8、Mybatis是否支持延迟加载?如果支持,原理是什么?
Mybatis仅支持association和collection关联查询时的延迟加载,可在配置中使用lazyLoadingEnable=truye|false
延迟加载的原理是使用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可以重复。
如果没有配置,id不能重复,毕竟namespace不是必须的,只是最佳实践而已。
原因就是namespace+id是作为Map<String, MappedStatement>的key使用的,如果没有namespace,就剩下id,那么id重复会导致数据相互覆盖,有了namespace,自然id就可以重复,namespace不同,namespace+id自然也不同。
10、Mybatis中如何执行批处理?
使用BatchExecutor完成批处理
11、Mybatis都有哪些执行器?它们之间的区别是什么?
Mybatis有三种基本的Executor执行器,SimpleExecutor,ResumeExecutor,BatchExecutor。
SimpleExecutor:每执行一次update或select,就开启一个statement对象,用完立即关闭statement对象。
ResumeExecutor:执行update或select,以SQL作为key查找statement,存在就使用,不存在就创建。
用完后,statement对象不立即关闭,而是存储在Map<String, Statement>中,供下一次使用。简而言之,就是重复使用Statement对象。
BatchExecutor:执行update,将所有的SQL都添加到批处理中(addBatch()),等待统一执行(executeBatch()),它缓存了多个Statement对象,每个statement对象都是addBatch()完毕后,等待逐一执行executeBatch()批处理。与JDBC批处理相同。
12、Mybatis中如何指定使用哪种Executor执行器?
在Mybatis配置文件中,可以指定默认的ExecutorType执行器类型,也可以手动给DefaultSqlSessionFactory的创建SqlSession的方法openSession()传递ExecutorType类型参数。
13、Mybatis是否可以映射Enum枚举类?
Mybatis可以映射枚举类,不但枚举,可以映射任何对象。映射方式为自定义一个TypeHandler,实现TypeHandler的setParameter()和getResult()接口方法。
TypeHandler有两个作用,一是完成Javatype到jdbctype的转换,而是返过来。分别表示设置SQL问好占位符参数和获取列查询结果。
14、Mybatis映射文件中 ,如果A标签通过include引用了B标签,请问,B标签能否定义在A标签的后面,还是必须定义在A标签的前面?
虽然Mybatis解析XML映射文件是按顺序解析的,但是被引用的B标签依然可以定义在任何地方,Mybatis能够正常识别。
原理是,Mybatis解析A标签时,发现了A标签引用了B标签,但是B标签尚未解析到,此时,Mybatis后将A标签标记为未解析状态,然后继续解析其他标签,包括B标签,等待所有标签解析完毕后,Mybatis会重新解析那些被标记为未解析的标签,此时再解析A时,B标签已经存在了,A标签也就可以正常解析了。
15、简述Mybatis的Xml映射文件和Mybatis内部数据结构之间的映射关系?
Mybatis将所有的Xml配置信息都封装到Configuration对象中。
在Xml映射文件中,<parameterMap>标签会被解析为ParameterMap对象,其子元素会被解析为ParameterMapping对象。<resultMap>标签会被解析为ResultMap对象,其每个子元素会被解析为ResultMapping对象。每个<select>,<insert>,<update>,<delete>标签均被解析为MappedStatement对象,标签内的SQL会被解析为BoundSQL对象。
16、为什么说Mybatis是半自动化ORM映射工具?它与全自动的区别在哪儿?
Hibernate属于全自动,关联对象或者集合时,可以根据对象关系模型直接获取,所以它是全自动。 Mybatis查询关联时,需要手动编写SQL实现,所以叫半自动。
17、当实体类中的属性名和表中的字段名不一样 ,怎么办 ?
第一种:通过SQL语句定义别名和属性名一致即可 第二种:通过< resultMap>标签映射字段名和实体的属性名
18、在mapper中如何传递多个参数?
第一种:使用占位符思想 在映射文件中使用#{0}, #{1}表示传递进来的参数顺序 使用@Param注解命名参数 第二种:使用集合(Map)或实体对象作为参数来装载。
19、接口绑定有几种实现方式,分别怎么实现?
接口绑定有两种方式实现 一是通过注解绑定,在接口方法上加上@Select,@Update来绑定 二是通过xml里面写的SQL来绑定,这时候mapper接口和xml需要同包同名
陈睿mikechen
10年+大厂架构经验,资深技术专家,就职于阿里巴巴、淘宝、百度等一线互联网大厂。
关注「mikechen」公众号,获取更多技术干货!
后台回复【面试】即可获取《史上最全阿里Java面试题总结》,后台回复【架构】,即可获取《阿里架构师进阶专题全部合集》