🚩MyBatis 面试题
目录
注意
本文最后更新于 2023-01-05,文中内容可能已过时。
#{}和${}的区别是什么?
#{}是预编译处理,${}
是字符串替换。
Mybatis 在处理#{}时,会将 sql 中的#{}替换为?号,调用
PreparedStatement 的set 方法来赋值;
Mybatis 在处理${}时,就是把${}替换成变量的值。使用#{}可以有效的防止 SQL 注入,提高系统安全性。
使用 ${} 的情况
- 当sql中表名是从参数中取的情况
- order by排序语句中,因为order by 后边必须跟字段名,这个字段名不能带引号,如果带引号会被识别会字符串,而不是字段。
Mybatis 是如何进行分页的?分页插件的原理是什么?
Mybatis 使用 RowBounds 对象进行分页,它是针对 ResultSet 结果集执行的内存分页,而非物理分页。可以在 sql 内直接书写带有物理分页的参数来完成物理分页功能,也可以使用分页插件来完成物理分页。 分页插件的基本原理是使用 Mybatis 提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的 sql,然后重写 sql,根据 dialect 方言,添加对应的物理分页语句和物理分页参数。
Mybatis 的一级、二级缓存?
基于 PerpetualCache,本质是一个 HashMap。
- 一级缓存(默认开启): 存储作用域为 Session,当 Session flush 或 close 时清空
- 二级缓存(默认关闭):存储作用域为 Mapper(Namespace)
- 需要实现 serializable 接口
- 只有会话提交或关闭后,一级缓存中的数据才会转移到二级缓存中
- C/U/D 操作后,该作用域下所有 select 中的缓存将被 clear。
MyBatis 执行流程?
- 读取配置文件
- SqlSessionFactory:唯一的会话工厂
- SqlSession:多个会话
- Executor:执行器,执行数据库操作并维护缓存
- MappedStatement:是 Executor 接口中的参数,封装了映射信息,接收入参,返回出参
MyBatis 开启延迟加载
lazyLoadingEnabled = true(默认false),原理:
- 使用 CGLIB 创建目标对象的代理对象
- 调用目标方法时,进入拦截器 invoke 方法,若目标方法为 null,执行 SQL
- 重新调用
Java 对象与 MySQL 对象如何映射?
MyBatis 默认使用 JDBC 的预编译语句来执行 SQL 语句。在将 String 类型的参数传递给 SQL 语句时,MyBatis 会自动将其转换为 VARCHAR 类型。