我是 javapub,一名 Markdown 程序员从👨💻,八股文种子选手。


《面试1v1》 连载中...


面试官: 恭喜你进到面试的最后一个环节!你对 MyBatis 比较熟悉吗?

候选人: 谢谢面试官!MyBatis 是我最喜欢且熟练使用的持久层框架之一。

面试官: 那很好,我们从基础开始问吧。什么是 MyBatis?

候选人: MyBatis 是一款优秀的持久层框架,它内部封装了 JDBC,使开发者只需要关注 SQL 语句本身,而不需要花费精力去处理加载驱动、创建连接、创建 statement 等繁杂的过程。

面试官: MyBatis 的工作原理能说一下吗?

候选人: MyBatis 的工作原理如下:

  1. 根据 XML 或注解的配置文件得到映射语句(也就是 SQL)。
  2. 把要调用的映射语句的参数传入并解析出 statement 中对应的占位符。
  3. 执行映射语句并得到结果。
  4. 把结果映射为 Java 对象并返回。

整个过程中最关键的部份是映射文件及映射过程。只有把 SQL 的执行结果映射成 Java 对象,才能达到 ORM 的目的。

面试官: 那它的核心组件有哪些?

候选人: MyBatis 的核心组件主要有:

  1. SqlSessionFactoryBuilder:用于创建 SqlSessionFactory,gue有 XML 或注解来配置。
  2. SqlSessionFactory:SqlSession 的工厂,用于创建 SqlSession。
  3. SqlSession:用于执行映射语句并commit、rollback 事务。
  4. Mapper 接口:用于定义映射语句(也就是 SQL),下面会详细解释。
  5. 映射文件:包含了映射语句,可以是 XML 或注解。

面试官: 既然你提到了 Mapper 接口,那它是什么?

候选人: Mapper 接口是 MyBatis 中非常重要的一个组件。它是由开发人员创建的接口,其中的方法直接对应映射文件中的 SQL 语句。 举个例子:

public interface UserMapper {
    User selectUser(int id);
}

然后在映射文件中:

<select id="selectUser" resultType="User">
  select * from user where id = #{id}
</select>

之后我们可以直接调用:

User user = session.getMapper(UserMapper.class).selectUser(1);

这样直接调用 Mapper 接口的方法就可以执行对应的 SQL 了,很方便。

面试官: 动态 SQL 又是什么?

候选人: MyBatis 的动态 SQL 是非常强大的一个功能。它允许开发人员在 XML 映射文件中直接插入一些逻辑,如:

  • if/else 分支
  • 动态选择部分内容
  • 提取重复代码块

举个例子:

<select id="findActiveBlogWithTitleLike"
     resultType="Blog">
  SELECT * FROM BLOG 
  WHERE state = 'ACTIVE' 
  <if test="title != null">
    AND title like #{title}
  </if>
</select>

这里通过 标签实现了动态条件查询。只有在方法调用时传入了 title 参数,SQL 语句才会添加 title 的条件判断。 这样的动态 SQL 使得数据库交互更加灵活,不需要在程序中进行大量的字符串拼接。

面试官: 最后两个问题,MyBatis 的缓存机制和插件机制能说一下吗?

候选人:

  1. MyBatis 包含一级缓存和二级缓存。
  • 一级缓存是 SqlSession 级别的缓
  • 一级缓存是 SqlSession 级别的缓存,在同一个 SqlSession 中多次调用同一个 Mapper 的方法,MyBatis 会直接从缓存中获取数据。
  • 二级缓存是 Mapper 级别的缓存,多个 SqlSession 去调用同一个 Mapper 的方法,MyBatis 会先去二级缓存中查找是否有数据,有的话直接返回,没有的话再查询数据库。
  1. MyBatis 的插件机制也很强大。我们可以通过实现 Interceptor 接口来编写插件,用于执行一些增强操作,比如:
  • 分页助手:通过拦截执行的 SQL 语句实现物理分页
  • 监控日志:监控 SQL 执行时间过长等
  • 读写分离:根据方法的注解实现读写分离 举个简单例子:
public class MyFirstPlugin implements Interceptor {
  @Override
  public Object intercept(Invocation invocation) throws Throwable {
    // 调用方法之前
    
    Object result = invocation.proceed();
    
    // 调用方法之后
    return result;
  }
}

然后在配置文件中进行配置:

<plugins>
  <plugin interceptor="org.mybatis.example.MyFirstPlugin"> 
    <property name="someProperty" value="100"/>
  </plugin> 
</plugins>

就可以启动对所有 SQL 执行的拦截了。

面试官: MyBatis 的内容我们就先讲到这里,你对它的理解很深入,加油!期待你加入我们团队!

候选人: 非常感谢面试官的赏识!我会继续努力学习,不断提高自己。也很期待加入贵团队一起成长!

最近我在更新《面试1v1》系列文章,主要以场景化的方式,讲解我们在面试中遇到的问题,致力于让每一位工程师拿到自己心仪的offer,感兴趣可以关注JavaPub追更!


《面试1v1》 连载中...


🎁目录合集:

Gitee:https://gitee.com/rodert/JavaPub

GitHub:https://github.com/Rodert/JavaPub

javapub.net.cn