第四节 关于mybatis和mybatisplus的常见面试题有哪些?

亮子 2025-09-07 12:32:22 35 0 0 0

好的,关于 MyBatis 和 MyBatis-Plus 的面试题是 Java 后端开发,尤其是中初级岗位非常高频的问题。下面我将它们分为两大板块,并附上详细的解答思路和要点,希望能帮助你准备面试。


第一部分:MyBatis 常见面试题

1. 什么是 MyBatis?它和 JDBC 有什么区别?

考察点: 对 MyBatis 的基本理解及其优势。
回答要点
* MyBatis: 一个优秀的**半自动化**的持久层ORM框架,它封装了 JDBC 的繁琐操作,使开发者只需关注 SQL 本身,而不需要花费精力去处理加载驱动、创建连接、创建 statement 等过程。
* 与 JDBC 的区别
* 简化开发: MyBatis 通过配置文件(XML/注解)管理 SQL,自动完成参数映射和结果集到 Java 对象的封装,避免了 JDBC 大量的重复代码。
* SQL 控制力: MyBatis 是“半自动化”的,开发者可以编写和优化原生的 SQL,保留了灵活性。而全自动化的 ORM(如 Hibernate)会自动生成 SQL,对复杂 SQL 的控制力较弱。
* 性能: MyBatis 可以编写高效、优化的 SQL,并且提供了一级/二级缓存机制,性能上通常比全自动 ORM 更好。

2. MyBatis 的核心组件有哪些?请描述它们的作用。

考察点: 对 MyBatis 框架架构的理解。
回答要点
* SqlSessionFactoryBuilder: 用于创建 SqlSessionFactory,一旦创建完成就可以丢弃。通常通过读取配置文件的输入流(InputStream)来构建。
* SqlSessionFactory: 一旦被创建,应该在应用运行期间一直存在。它是生产 SqlSession 的工厂,是线程安全的。
* SqlSession: 是 MyBatis 工作的主要Java接口,包含了执行SQL、管理事务、获取Mapper等方法。它是**非线程安全**的,每次请求都应该创建一个新的 SqlSession,使用完毕后必须关闭。
* Executor: SQL 执行器,是 MyBatis 调度的核心,负责SQL的动态生成和查询缓存的维护。
* MappedStatement: 封装了 SQL 语句的详细信息(如id、sqlSource、输入输出参数等)。
* SQL Mapper: 由 Java 接口和 XML 文件(或注解)构成,定义了具体的 SQL 和映射规则。

3. #{}${} 的区别是什么?

考察点: SQL 注入、预编译的理解。这是**必问**的高频题。
回答要点
* #{}
* 是**预编译**处理。MyBatis 会将其替换为 ?,然后使用 PreparedStatement 的 set 方法来安全地赋值。
* 可以有效地防止 SQL 注入
* 会对传入的数据自动加上**单引号**(适用于字符串、日期等类型)。
* ${}
* 是**字符串替换**。MyBatis 会将其直接替换为变量的值,拼接在SQL语句中。
* 存在 SQL 注入的风险。
* 不会自动加引号,直接插入到SQL中(适用于动态传入表名、字段名等非值参数的场景)。
* 总结: 绝大多数情况下,**都应该使用 #{}**。只有在需要动态传入数据库表名、列名等**非值参数**时,才不得已使用 ${},并且需要对外部输入进行严格的过滤和安全检查。

4. MyBatis 的一级缓存和二级缓存有什么区别?

考察点: 对 MyBatis 缓存机制的理解。
回答要点

特性 一级缓存 二级缓存
作用域 SqlSession 级别 Mapper (Namespace) 级别
默认开启 否,需要在配置文件中显式开启 (<setting name="cacheEnabled" value="true"/>) 并在 Mapper.xml 中添加 <cache/> 标签
如何失效 当执行 UPDATE, INSERT, DELETE 操作,或调用 sqlSession.clearCache()、关闭 SqlSession 时,缓存会清空。 配置的失效策略(如 LRU、FIFO等)或执行了同命名空间下的更新操作。
共享性 同一个 SqlSession 内共享。 所有 SqlSession 共享,只要属于同一个 Mapper。

5. MyBatis 的动态 SQL 有哪些标签?有什么作用?

考察点: 对 MyBatis 灵活拼接 SQL 能力的掌握。
回答要点
* <if>: 条件判断。
* <choose>(<when>, <otherwise>): 类似于 Java 中的 switch-case 语句,多选一。
* <trim>: 可以灵活地去除 SQL 语句开头或结尾指定的字符(如 AND, OR, ,),是 whereset 的更通用实现。
* <where>: 智能处理 WHERE 子句,如果标签内无内容,则不生成 WHERE 关键字;会自动去除开头多余的 ANDOR
* <set>: 智能处理 UPDATE 语句中的 SET 子句,会自动去除结尾多余的逗号 ,
* <foreach>: 遍历集合,常用于 IN 条件或批量操作(如 INSERT INTO ... VALUES (...), (...))。


第二部分:MyBatis-Plus 常见面试题

1. MyBatis-Plus (MP) 是什么?它和 MyBatis 有什么关系?

考察点: 对 MP 的定位和理解。
回答要点
* MP 是 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,旨在简化开发、提高效率。
* 它内置了通用的 Mapper 和 Service,只需通过简单的继承,即可获得大部分单表操作的 CRUD 方法,无需编写任何 SQL 或 XML。
* 它提供了强大的**条件构造器**、**代码生成器**、**分页插件**等功能,极大地提升了开发效率。

2. MyBatis-Plus 的主要优点有哪些?

考察点: 对 MP 价值的认识。
回答要点
* 无侵入: 只做增强,引入它不会对现有 MyBatis 工程产生影响。
* 损耗小: 启动即会自动注入基本 CURD,性能基本无损耗。
* 强大的 CRUD 操作: 内置通用 Mapper、通用 Service,仅通过少量配置即可实现单表 CRUD 操作。
* 强大的条件构造器: 使用 QueryWrapperUpdateWrapper 可以方便地编写动态查询和更新条件。
* 内置分页插件: 基于 MyBatis 物理分页,开发者无需关心具体实现,配置好插件后即可轻松实现分页。
* 内置代码生成器: 可快速生成 Entity、Mapper、Mapper XML、Service、Controller 等各个模块的代码。

3. 请说明 BaseMapper<T>IService<T> 的作用。

考察点: 对 MP 核心接口的掌握。
回答要点
* BaseMapper<T>
* 需要由**自定义的 Mapper 接口**来继承。
* 它提供了非常丰富的单表 CRUD 方法,如 selectById, selectList, insert, updateById, deleteById 等。
* 继承后,你的 Mapper 接口就立刻拥有了这些方法,无需编写 XML。
* IService<T>
* 需要由**自定义的 Service 接口**来继承。
* 它进一步封装了更常用的业务层方法,如 saveOrUpdate, list, page, getById 等。
* 通常我们会有一个对应的实现类继承 ServiceImpl<M, T>,从而获得这些方法的默认实现,无需自己写实现代码。

4. 解释一下 QueryWrapperLambdaQueryWrapper 的区别。

考察点: 对 MP 条件构造器高级用法的理解。
回答要点
* QueryWrapper
* 使用字符串表示字段名,例如:.eq("name", "张三")
* 缺点: 容易因手写错误导致运行时异常,且不支持编译时检查和代码智能提示。
* LambdaQueryWrapper
* 通过 Lambda 表达式获取字段名,例如:.eq(User::getName, "张三")
* 优点类型安全,编译时就能检查出字段名错误,并且有代码智能提示,重构友好。**推荐使用**。

5. MyBatis-Plus 是如何实现分页的?

考察点: 对 MP 分页插件原理的理解。
回答要点
1. 配置分页插件: 必须先在 Spring Boot 的配置类中声明一个 PaginationInnerInterceptor Bean。
2. 使用分页对象: 在需要分页的方法中,创建一个 Page<T> 对象,传入当前页码和每页大小。
3. 执行查询: 调用 MP 提供的分页方法(如 page(page, queryWrapper)selectPage(page, queryWrapper))。
4. 原理: MP 的分页插件会拦截Executor,在执行原始SQL前,自动生成并执行一条 COUNT(*) 语句查询总数,然后对原始SQL拼接数据库特有的分页语句(如 LIMIT),最终将分页数据和其他信息封装到 Page<T> 对象中返回。


综合与对比题

1. 你更喜欢用 MyBatis 还是 MyBatis-Plus?为什么?

考察点: 个人技术选型的思考和权衡能力。
回答思路
* 这是一个开放性问题,没有标准答案,但可以展示你的思考。
* 如果倾向于 MyBatis-Plus: 可以强调其开发效率高,减少了大量模板代码,特别是对于单表操作和标准业务场景。内置的分页和条件构造器非常方便。
* 如果倾向于原生 MyBatis: 可以强调其对复杂SQL和存储过程的完全控制力,在极度复杂的业务场景下更灵活,没有MP的抽象层,更“接地气”。
* 一个平衡的回答: “对于常规的单表CRUD和简单查询,我会优先使用 MyBatis-Plus 来提升开发效率。而对于非常复杂的多表关联查询、存储过程调用或者需要高度优化的SQL场景,我会选择使用原生 MyBatis 来编写手动的 SQL 和结果映射,以获得最大的控制权。两者并不冲突,甚至可以在一个项目中混合使用。”

2. MyBatis-Plus 是完美的吗?它有什么缺点或需要注意的地方?

考察点: 批判性思维和对技术的深度理解。
回答要点
* 学习成本: 需要学习其特有的API(如Wrapper),团队需要统一规范。
* 抽象代价: 虽然方便,但多了一层抽象,在极端复杂的动态SQL场景下,可能不如直接写 XML 灵活和直观。
* 依赖性: 项目会强依赖 MP,如果未来 MP 停止维护或项目想迁移到其他技术栈,会有一定的迁移成本。
* N+1 问题: 和任何 ORM 一样,如果不注意,使用其提供的方法(如 selectList)懒加载关联对象,很容易造成 N+1 查询问题,需要通过手动编写SQL或配置来避免。

希望这份整理能对你的面试有所帮助!祝你成功!