Mybatis常见面试题
-
#{}和¥{}的区别是什么?
-
【#】:底层执行SQL使用PreparedStatement对象,预编译SQL,相对安全。入参使用占位符的方式。
-
【$】:底层执行SQL使用Statement对象,入参使用SQL拼接的方式,存在SQL注入问题。
-
-
xml映射文件中,除了常见的select、insert、update、delete还有哪些标签。
- 根标签,namespace要求与接口的全类名一致。
- 标签,用于编写sql片段,可以使用标签引入sql片段。
- 标签:描述如何从数据库结果集中加载对象。
- 一般是resultType解决不了的问题,可以使用resultMap。比如多表查询返回多个结果集等复杂情况使用。
- resultType属性:设置结果集期望返回的类型。
- 动态的九个子标签。
-
Dao接口的工作原理是什么?Dao接口里的方法,参数不同,方法能重载吗?
Dao接口的工作原理是JDK动态代理,Mybatis运行时回使用动态代理为Dao生成代理proxy对象,代理对象会拦截接口方法,执行MapedStatement代表的sql,然后返回sql执行结果。
- Mybatis 通过解析 XML 和 mapper 接口上的注解,生成 sql 对应的 MappedStatement 实例,并放入 SqlSessionTemplate 中 configuration 类属性中
Dao接口可以重载多个方法,但是多个接口对应的映射只能有一个。
- 方法的参数不同,可以使用在sql语句中使用动态sql。
有多个有参方法时,参数数量必须一致,并且使用相同的@Param注解给参数命名。
-
Mybatis是如何分页的?分页插件原理是什么?
在mybatis-config.xml中使用分页插件pagehelper,调用startPage方法,在执行SQL语句时,会为SQL加上limit语句。
-
简述Mybatis的插件运行原理,如何编写一个插件?
MyBatis 仅可以编写针对
ParameterHandler
、ResultSetHandler
、StatementHandler
、Executor
这 4 种接口的插件,MyBatis 使用 JDK 的动态代理,为需要拦截的接口生成代理对象以实现接口方法拦截功能,每当执行这 4 种接口对象的方法时,就会进入拦截方法,具体就是InvocationHandler
的invoke()
方法,当然,只会拦截那些你指定需要拦截的方法。实现 MyBatis 的
Interceptor
接口并复写intercept()
方法,然后在给插件编写注解,指定要拦截哪一个接口的哪些方法即可,记住,别忘了在配置文件中配置你编写的插件。 -
Mybatis执行批量插入,能返回数据库主键列表吗?
批量插入:使用标签,和标签配合,可以实现批量插入。
可以返回数据库主键列表。
-
Mybatis动态sql是做什么的?都有哪些动态sql,能简述一下动态sql的执行原理吗?
使用动态sql,可以根据不同条件编写sql语句。MyBatis 提供了 9 种动态 sql 标签:
<if></if>
<where></where>(trim,set)
<choose></choose>(when, otherwise)
<foreach></foreach>
<bind/>
执行原理:其执行原理为,使用 OGNL (对象导航图语言)来实现动态 sql 的功能。
-
Mybatis是如何将sql执行结果封装为目标对象并返回的?
通过获得列名和属性名的映射关系,Mybatis通过反射创建对象,并且逐一给对象的属性赋值并返回。
-
Mybatis能一对一,一对多关联查询吗?
关联对象查询实现方式:可以单独发送一个sql查询关联对象,再赋值给主对象。
或者通过join嵌套查询。具体实现方式:
- 使用resultMap自定义映射,resultMap的子标签association定义一对一的关联关系。collection标签,定义一对多的关联关系。
-
Mybatis是否支持延迟加载?如果支持,原理是什么?
延迟加载:需要即加载,不需要就不加载。可以提高程序运行效率。
<!-- 开启延迟加载 --> <setting name="lazyLoadingEnabled" value="true"/>
使用
CGLIB
创建目标对象的代理对象,调用目标方法,进入拦截器方法,拦截器发现是null值,就会发送sql语句,把具体值查询上来。-
CGLIB是一个功能强大,高性能的代码生成包。它为没有实现接口的类提供代理,为JDK的动态代理提供了很好的补充。
-
通过Mybatis拦截器我们可以拦截某些方法的调用,我们可以选择在这些被拦截的方法执行前后加上某些逻辑,也可以在执行这些被拦截的方法时执行自己的逻辑而不再执行被拦截的方法。所以Mybatis拦截器的使用范围是非常广泛的。
-
-
Mybatis的xml映射文件中,不同xml映射文件,id是否可以重复?
不同的 xml 映射文件,如果配置了 namespace,那么 id 可以重复;如果没有配置 namespace,那么 id 不能重复;毕竟 namespace 不是必须的,只是最佳实践而已。
原因就是 namespace+id 是作为
Map<String, MappedStatement>
的 key 使用的,如果没有 namespace,就剩下 id,那么,id 重复会导致数据互相覆盖。有了 namespace,自然 id 就可以重复,namespace 不同,namespace+id 自然也就不同。 -
Mybatis批处理
使用
BatchExecutor
(批处理执行器) 完成批处理。(批量插入,删除) -
Mybatis都有哪些Executor执行器,之间的区别?
MyBatis 有三种基本的
Executor
执行器:SimpleExecutor
: 每执行一次 update 或 select,就开启一个 Statement 对象,用完立刻关闭 Statement 对象。ReuseExecutor
: 执行 update 或 select,以 sql 作为 key 查找 Statement 对象,存在就使用,不存在就创建,用完后,不关闭 Statement 对象,而是放置于 Map<String, Statement>内,供下一次使用。简言之,就是重复使用 Statement 对象。BatchExecutor
:执行 update(没有 select,JDBC 批处理不支持 select),将所有 sql 都添加到批处理中(addBatch()),等待统一执行(executeBatch()),它缓存了多个 Statement 对象,每个 Statement 对象都是 addBatch()完毕后,等待逐一执行 executeBatch()批处理。与 JDBC 批处理相同。
作用范围:
Executor
的这些特点,都严格限制在 SqlSession 生命周期范围内。 -
Mybatis中如何指定使用哪一种Executor?
在 MyBatis 配置文件中,可以指定默认的
ExecutorType
执行器类型,也可以手动给DefaultSqlSessionFactory
的创建 SqlSession 的方法传递ExecutorType
类型参数。 -
Mybatis是否可以映射Enum枚举类
MyBatis 可以映射枚举类,不单可以映射枚举类,MyBatis 可以映射任何对象到表的一列上。映射方式为自定义一个
TypeHandler
,实现TypeHandler
的setParameter()
和getResult()
接口方法。TypeHandler
有两个作用:- 一是完成从 javaType 至 jdbcType 的转换;
- 二是完成 jdbcType 至 javaType 的转换,体现为
setParameter()
和getResult()
两个方法,分别代表设置 sql 问号占位符参数和获取列查询结果。
-
MyBatis 映射文件中,如果 A 标签通过 include 引用了 B 标签的内容,请问,B 标签能否定义在 A 标签的后面,还是说必须定义在 A 标签的前面?
虽然 MyBatis 解析 xml 映射文件是按照顺序解析的,但是,被引用的 B 标签依然可以定义在任何地方,MyBatis 都可以正确识别。
原理是,MyBatis 解析 A 标签,发现 A 标签引用了 B 标签,但是 B 标签尚未解析到,尚不存在,此时,MyBatis 会将 A 标签标记为未解析状态,然后继续解析余下的标签,包含 B 标签,待所有标签解析完毕,MyBatis 会重新解析那些被标记为未解析的标签,此时再解析 A 标签时,B 标签已经存在,A 标签也就可以正常解析完成了。
-
简述 MyBatis 的 xml 映射文件和 MyBatis 内部数据结构之间的映射关系?
MyBatis 将所有 xml 配置信息都封装到 All-In-One 重量级对象 Configuration 内部。在 xml 映射文件中,
<parameterMap>
标签会被解析为ParameterMap
对象,其每个子元素会被解析为 ParameterMapping 对象。<resultMap>
标签会被解析为ResultMap
对象,其每个子元素会被解析为ResultMapping
对象。每一个<select>、<insert>、<update>、<delete>
标签均会被解析为MappedStatement
对象,标签内的 sql 会被解析为 BoundSql 对象。 -
为什么说 MyBatis 是半自动持久化层 ORM 映射工具?它与全自动的区别在哪里?
半自动化:
-
Hibernate 属于全自动 ORM 映射工具,使用 Hibernate 不需要手动编写sql语句。所以它是全自动的。
-
而 MyBatis 在查询关联对象或关联集合对象时,需要手动编写 sql 来完成,所以,称之为半自动 ORM 映射工具。手写sql,为优化SQL提供了可能。
ORM框架:遵循对象关系映射。
持久化层:数据可以持久化,将数据不仅仅放在内存中,而是保存在数据库中。也就是我们常说的DAO层。Mybatis可以帮助我们更方便地从数据库中取出数据、插入数据等。
-