面试题篇-11-Mybatis相关面试题

1. 说一说 Mybatis 里面的缓存机制

Mybatis 里面设计的二级缓存是用来提升数据的检索效率,避免每次数据的访问都需要去查询数据库。

一级缓存,是SqlSession 级别的缓存,也叫本地缓存,因为每个用户在执行查询的时候都需要使用SqlSession 来执行,
为了避免每次都去查数据库,Mybatis 把查询出来的数据保存到SqlSession 的本地缓存中,后续的SQL 如果命中缓存,就可以直接从本地缓存读取了。

如果想要实现跨 SqlSession 级别的缓存?那么一级缓存就无法实现了,因此在 Mybatis 里面引入了二级缓存,就是当多个用户
在查询数据的时候,只有有任何一个 SqlSession 拿到了数据就会放入到二级缓存里面,其他的SqlSession 就可以从二级缓存加载数据。
在这里插入图片描述

  • 一级缓存的具体实现原理是:
    在SqlSession 里面持有一个Executor,每个 Executor 中有一个LocalCache 对象。当用户发起查询的时候,Mybatis 会根据执行语句在Local Cache 里面查询,如果没命中,再去查询数据库并写入到 LocalCache,否则直接返回。
    所以,以及缓存的生命周期是 SqlSessiion,而且在多个 Sqlsession 或者分布式环境下,可能会导致数据库写操作出现脏数据。
  • 二级缓存的具体实现原理是:
    使用CachingExecutor 装饰了 Executor,所以在进入一级缓存的查询流程之前,会先通过CachingExecutor 进行二级缓存的查询。
    开启二级缓存以后,会被多个 SqlSession 共享,所以它是一个全局缓存。因此它的查询流程是先查二级缓存,再查一级缓存,最后再查数据库。另外,MyBatis 的二级缓存相对于一级缓存来说,实现了 SqlSession 之间缓存数据的共享,同时缓存粒度也能够到 namespace 级别,并且还可以通过 Cache 接口实现类不同的组合,对 Cache 的可控性也更强。

在这里插入图片描述
二级缓存的设计思想非常常见,比如 Nacos、Eureka 都用到了

2. Mybatis 中#{}和${}的区别是什么?

首先,Mybatis 提供到的#号占位符和$号占位符,都是实现动态SQL 的一种方式,通过这两种方式把参数传递到 XML 之后,
在执行操作之前,Mybatis 会对这两种占位符进行动态解析。

  • #号占位符,等同于jdbc 里面的?号占位符。
    它相当于向PreparedStatement 中的预处理语句中设置参数,
    而PreparedStatement 中的sql 语句是预编译的,SQL 语句中使用了占位符,规定了 sql 语句的结构。
    并且在设置参数的时候,如果有特殊字符,会自动进行转义。所以#号占位符可以防止SQL 注入。
    在这里插入图片描述
  • 而使用$的方式传参,相当于直接把参数拼接到了原始的 SQL 里面,Mybatis不会对它进行特殊处理。

所以$#最大的区别在于,前者是动态参数,后者是占位符, 动态参数无法防止 SQL注入的问题,所以在实际应用中,应该尽可能的使用#号占位符。
另外,$符号的动态传参,可以适合应用在一些动态 SQL 场景中,比如动态传递表名、动态设置排序字段等。

3. Mybatis 是如何进行分页的

数据进行分页是最基础的功能,一般可以把分页分成两类:

  • 逻辑分页,先查询出所有的数据缓存到内存,再根据业务相关需求,从内存数据中筛选出合适的数据进行分页。
  • 物理分页 ,直接利用数据库支持的分页语法来实现,比如Mysql 里面提供了分页关键词Limit

Mybatis 提供了四种分页方式:

  • 在Mybatis Mapper 配置文件里面直接写分页 SQL,这种方式比较灵活,实现也简单。
  • RowBounds 实现逻辑分页,也就是一次性加载所有符合查询条件的目标数据,根据分页参数值在内存中实现分页。
    当然,在数据量比较大的情况下,JDBC 驱动本身会做一些优化,也就是不会把所有结果存储在ResultSet 里面,
    而是只加载一部分数据,再根据需求去数据库里面加载。
    这种方式不适合数据量较大的场景,而且有可能会频繁访问数据库造成比较大的压力。
  • Interceptor 拦截器实现,通过拦截需要分页的 select 语句,然后在这个sql 语句里面动态拼接分页关键字,从而实现分页查询。
    Interceptor 是Mybatis 提供的一种针对不同生命周期的拦截器,比如:
    • 拦截执行器方法
    • 拦截参数的处理
    • 拦截结果集的处理
    • 拦截SQL 语法构建的处理
      在这里插入图片描述
      这种方式的好处,就是可以提供统一的处理机制,不需要我们再单独去维护分页相关的功能。
  • 插件(PageHelper)及(MyBaits-Plus、tkmybatis)框架实现这些插件本质上也是使用Mybatis 的拦截器来实现的。
    只是他们帮我们实现了扩展和封装,节省了分页扩展封装的工作量,在实际开发中,只需要拿来即用即可。

总结: 认为有三种方式来实现分页:

  • 第一种,直接在 Select 语句上增加数据库提供的分页关键字,然后在应用程序里面传递当前页,以及每页展示条数即可。
  • 第二种,使用Mybatis 提供的RowBounds 对象,实现内存级别分页。
  • 第三种,基于Mybatis 里面的Interceptor 拦截器,在select 语句执行之前动态拼接分页关键字。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Alan0517

感谢您的鼓励与支持!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值