1、 MyBatis 中 #{}和 ${}的区别是什么?
#{}是预编译处理,${}是字元替换。 在使用 #{}时,MyBatis 会将 SQL 中的 #{}替换成“?”,配合 PreparedStatement 的 set 方法赋值,这样可以有效的防止 SQL 注入,保证程式的执行安全。
2、 MyBatis 有几种分页方式?
分页方式:逻辑分页和物理分页。
逻辑分页: 使用 MyBatis 自带的 RowBounds 进行分页,它是一次性查询很多资料,然后在资料中再进行检索。
物理分页: 自己手写 SQL 分页或使用分页外挂 PageHelper,去数据库查询指定条数的分页资料的形式。
3、RowBounds 是一次性查询全部结果吗?为什么?
RowBounds 表面是在“所有”资料中检索资料,其实并非是一次性查询出所有资料,因为 MyBatis 是对 jdbc 的封装,在 jdbc 驱动中有一个 Fetch Size 的配置,它规定了每次最多从数据库查询多少条资料,假如你要查询更多资料,它会在你执行 next()的时候,去查询更多的资料。就好比你去自动取款机取 10000 元,但取款机每次最多能取 2500 元,所以你要取 4 次才能把钱取完。只是对于 jdbc 来说,当你呼叫 next()的时候会自动帮你完成查询工作。这样做的好处可以有效的防止内存溢位。
4、MyBatis 逻辑分页和物理分页的区别是什么?
逻辑分页是一次性查询很多资料,然后再在结果中检索分页的资料。这样做弊端是需要消耗大量的内存、有内存溢位的风险、对数据库压力较大。物理分页是从数据库查询指定条数的资料,弥补了一次性全部查出的所有资料的种种缺点,比如需要大量的内存,对数据库查询压力较大等问题。5、MyBatis 是否支援延迟载入?延迟载入的原理是什么?
MyBatis 支援延迟载入,设定 lazyLoadingEnabled=true 即可。
延迟载入的原理的是呼叫的时候触发载入,而不是在初始化的时候就载入资讯。比如呼叫 a. getB(). getName(),这个时候发现 a. getB() 的值为 null,此时会单独触发事先储存好的关联 B 物件的 SQL,先查询出来 B,然后再呼叫 a. setB(b),而这时候再呼叫 a. getB(). getName() 就有值了,这就是延迟载入的基本原理。
6、 说一下 MyBatis 的一级快取和二级快取?
一级快取:基于 PerpetualCache 的 HashMap 本地快取,它的宣告周期是和 SQLSession 一致的,有多个 SQLSession 或者分散式的环境中数据库操作,可能会出现脏资料。当 Session flush 或 close 之后,该 Session 中的所有 Cache 就将清空,预设一级快取是开启的。二级快取:也是基于 PerpetualCache 的 HashMap 本地快取,不同在于其储存作用域为 Mapper 级别的,如果多个SQLSession之间需要的共享快取,则需要使用到二级快取,并且二级快取可自定义储存源,如 Ehcache。预设不开启二级快取,要开启二级快取,使用二级快取属性类需要实现 Serializable 序列化界面(可用来储存物件的状态)。开启二级快取资料查询流程:二级快取 -> 一级快取 -> 数据库。
快取更新机制:当某一个作用域(一级快取 Session/二级快取 Mapper)进行了C/U/D 操作后,预设该作用域下所有 select 中的快取将被 clear。
7、 MyBatis 和 hibernate 的区别有哪些?
灵活性:MyBatis 更加灵活,自己可以写 SQL 语句,使用起来比较方便。可移植性:MyBatis 有很多自己写的 SQL,因为每个数据库的 SQL 可以不相同,所以可移植性比较差。学习和使用门槛:MyBatis 入门比较简单,使用门槛也更低。二级快取:hibernate 拥有更好的二级快取,它的二级快取可以自行更换为第三方的二级快取。8、MyBatis 有哪些执行器(Executor)?
MyBatis 有三种基本的Executor执行器:
SimpleExecutor:每执行一次 update 或 select 就开启一个 Statement 物件,用完立刻关闭 Statement 物件;ReuseExecutor:执行 update 或 select,以 SQL 作为 key 查询 Statement 物件,存在就使用,不存在就建立,用完后不关闭 Statement 物件,而是放置于 Map 内供下一次使用。简言之,就是重复使用 Statement 物件;BatchExecutor:执行 update(没有 select,jdbc 批处理不支援 select),将所有 SQL 都新增到批处理中(addBatch()),等待统一执行(executeBatch()),它快取了多个 Statement 物件,每个 Statement 物件都是 addBatch()完毕后,等待逐一执行 executeBatch()批处理,与 jdbc 批处理相同。9、MyBatis 分页外挂的实现原理是什么?
分页外挂的基本原理是使用 MyBatis 提供的外挂界面,实现自定义外挂,在外挂的拦截方法内拦截待执行的 SQL,然后重写 SQL,根据 dialect 方言,新增对应的物理分页语句和物理分页引数。
10、 MyBatis 如何编写一个自定义外挂?
自定义外挂实现原理
MyBatis 自定义外挂针对 MyBatis 四大物件(Executor、StatementHandler、ParameterHandler、ResultSetHandler)进行拦截:
Executor:拦截内部执行器,它负责呼叫 StatementHandler 操作数据库,并把结果集通过 ResultSetHandler 进行自动对映,另外它还处理了二级快取的操作;StatementHandler:拦截 SQL 语法构建的处理,它是 MyBatis 直接和数据库执行 SQL 指令码的物件,另外它也实现了 MyBatis 的一级快取;ParameterHandler:拦截引数的处理;ResultSetHandler:拦截结果集的处理。自定义外挂实现关键
MyBatis 外挂要实现 Interceptor 界面,界面包含的方法,如下:

setProperties 方法是在 MyBatis 进行配置外挂的时候可以配置自定义相关属性,即:界面实现物件的引数配置;plugin 方法是外挂用于封装目标物件的,通过该方法我们可以返回目标物件本身,也可以返回一个它的代理,可以决定是否要进行拦截进而决定要返回一个什么样的目标物件,官方提供了示例:return Plugin. wrap(target, this);intercept 方法就是要进行拦截的时候要执行的方法。自定义外挂实现示例
官方外挂实现:






























