1. Mybatis 是什么?它的核心工作原理是什么?
-
是什么 :Mybatis 是一个优秀的持久层框架,它避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。它使用简单的 XML 或注解来配置和映射原始类型、Map 和 POJO 到数据库的记录。
-
核心原理 :Mybatis 通过 SQL Mapper 机制,将 SQL 语句和 Java 方法进行绑定。开发者只需定义 SQL 语句,Mybatis 就会负责底层与数据库的交互,并将查询结果自动映射为 Java 对象。
2. 为什么说 Mybatis 是一个半自动化的 ORM 框架?它和 Hibernate 有什么区别?
-
半自动化 :Mybatis 的 SQL 语句需要开发者手动编写,它只是将 SQL 执行结果自动映射为 Java 对象。它让开发者对 SQL 有完全的控制权。
-
区别:
-
SQL 控制:Mybatis 让开发者自由编写 SQL,可以进行 SQL 优化;Hibernate 则是完全的 ORM,它自动生成 SQL,开发者无法直接控制。
-
学习成本:Mybatis 简单易学,入门快;Hibernate 概念较多,学习曲线陡峭。
-
灵活性:Mybatis 更灵活,适合复杂的、需要手动优化的业务 SQL;Hibernate 适合 CRUD 简单、业务不复杂的场景。
-
3. Mybatis 的配置文件有哪些?
Mybatis 的核心配置文件主要有两个:
-
mybatis-config.xml
:Mybatis 的全局配置文件,包含了数据库连接、类型别名、插件、映射器(Mapper)等核心配置。 -
Mapper XML 文件:用于定义 SQL 语句和结果映射的 XML 文件,每个 Mapper 接口通常对应一个 XML 文件。
4. #
和 $
符号有什么区别?
-
#
:表示一个预编译参数占位符 。Mybatis 在处理时,会将#
替换为?
,并使用 PreparedStatement 来执行,可以有效防止 SQL 注入。 -
$
:表示一个字符串占位符 。Mybatis 会直接将$
替换为变量的字面量值,不进行预编译。不安全,容易导致 SQL 注入。通常用于动态传入表名或排序列名。
5. 什么是动态 SQL?有哪些常用的标签?
动态 SQL 是 Mybatis 的强大特性,它允许你根据传入的参数,动态地拼接 SQL 语句。
常用的动态 SQL 标签有:
-
<if>
:简单的条件判断。 -
<choose>
,<when>
,<otherwise>
:类似 Java 的if/else if/else
结构。 -
<where>
:自动添加WHERE
关键字,并处理 SQL 语句开头多余的AND
或OR
。 -
<set>
:用于UPDATE
语句,自动处理更新字段之间多余的逗号。 -
<foreach>
:用于构建IN
语句或批量插入。
6. 如何传递多个参数?
有三种主要方式:
-
使用
@Param
注解:最推荐的方式,清晰直观。Java
User selectUser(@Param("name") String name, @Param("age") int age);
-
使用
Map
:将参数放入一个 Map 中,通过键名访问。 -
使用 JavaBean/POJO:将参数封装成一个 Java 对象,在 XML 中通过对象的属性名访问。
7. resultType
和 resultMap
的区别?
-
resultType
:用于将查询结果直接映射为简单数据类型 或简单 POJO 对象 。要求数据库列名和 POJO 的属性名完全一致,否则需要使用as
别名。 -
resultMap
:用于复杂的自定义映射 。当数据库列名和 POJO 属性名不一致、需要处理复杂关系(如一对一、一对多)或进行复杂数据类型转换时,必须使用resultMap
。
8. 如何实现一对一和一对多关系映射?
-
一对一 :使用
<association>
标签。 -
一对多 :使用
<collection>
标签。
这两个标签都可以通过嵌套查询(N+1 问题)或嵌套结果(一次查询解决)两种方式来实现。
9. Mybatis 的缓存机制是怎样的?
Mybatis 提供了两级缓存:
-
一级缓存(默认开启) :
SqlSession
级别的缓存。在同一个SqlSession
中,如果执行相同的查询,会直接从缓存中获取结果。 -
二级缓存(默认关闭) :
Mapper
级别的缓存。多个SqlSession
可以共享缓存。需要手动开启。
10. 什么是懒加载(Lazy Loading)?如何配置?
懒加载 也叫延迟加载,指在查询主对象时,不立即查询其关联对象的数据,而是等到真正使用到关联对象时才去查询。这可以避免不必要的数据库查询,减少 N+1 问题。
- 配置 :在
mybatis-config.xml
中将lazyLoadingEnabled
设置为true
。
11. SqlSessionFactory
和 SqlSession
有什么区别?
-
SqlSessionFactory
:是 Mybatis 的核心类,用于创建SqlSession
对象。一个应用通常只有一个SqlSessionFactory
实例。 -
SqlSession
:是 Mybatis 与数据库交互的会话,包含了所有执行 SQL 的方法。SqlSession
不是线程安全的,每次请求都应该新创建一个。
12. 为什么说 Mapper 接口和 Mapper XML 是绑定的?
Mybatis 通过两种方式将它们绑定:
-
命名空间(Namespace) :XML 文件的
namespace
必须是 Mapper 接口的全限定名。 -
方法名 :XML 文件中
<select>
、<insert>
等标签的id
必须和 Mapper 接口中的方法名一致。
13. Mybatis 如何获取自增主键?
可以使用 <insert>
标签的 useGeneratedKeys
和 keyProperty
属性。
-
useGeneratedKeys="true"
:启用获取自增主键的功能。 -
keyProperty
:将自增主键的值设置到 Java 对象的哪个属性中。
14. 什么是 N+1 查询问题?如何解决?
N+1 问题是指,当查询一个主列表时,Mybatis 会先执行一次查询获取主列表,然后针对列表中的每一个 对象,再单独执行一次查询去获取其关联对象,总共需要 1 + N 次查询。
-
解决方案:
-
使用联结查询 :使用
<association>
或<collection>
的嵌套结果(Result Map),通过一次JOIN
查询获取所有数据。 -
使用懒加载:如果不需要立即使用关联对象,可以开启懒加载来延迟查询。
-
15. 解释下 Mybatis 的生命周期对象
-
SqlSessionFactoryBuilder
:构建器,用于从 XML 或 Java 配置中创建SqlSessionFactory
,用完即弃。 -
SqlSessionFactory
:会话工厂,用于创建SqlSession
。它是线程安全的,通常是单例的。 -
SqlSession
:会话,用于执行 SQL。它不是线程安全的,每次请求都应创建新实例。 -
Mapper
:映射器接口,它的实例由SqlSession
创建,用于调用 XML 中定义的 SQL。
16. Mybatis 的 XML 映射文件中 <select>
标签的属性有哪些?
-
id
:映射的 Java 方法名。 -
parameterType
:入参类型。 -
resultType
:返回值类型,简单类型或 POJO。 -
resultMap
:自定义结果集映射。 -
statementType
:可选STATEMENT
、PREPARED
或CALLABLE
,默认为PREPARED
。
17. 如何整合 Mybatis 和 Spring?
主要通过 mybatis-spring
模块进行整合。
-
在 Spring 配置中,配置
SqlSessionFactoryBean
,注入数据源和 Mybatis 核心配置文件。 -
配置
MapperScannerConfigurer
或@MapperScan
注解,让 Spring 自动扫描 Mapper 接口,并将其注册为 Bean。
18. 为什么要使用 Mybatis?它的优点是什么?
-
SQL 灵活性:开发者可以完全控制 SQL,方便进行 SQL 优化。
-
半自动化:兼顾了 SQL 编写的灵活性和 ORM 框架的自动化映射。
-
配置简单:配置相对简单,学习成本低。
-
SQL 与代码分离:将 SQL 语句从 Java 代码中解耦,便于维护。
19. Mybatis 的执行流程是怎样的?
-
加载
mybatis-config.xml
和 Mapper XML 文件,创建SqlSessionFactory
。 -
通过
SqlSessionFactory
创建SqlSession
。 -
通过
SqlSession
获得 Mapper 接口的代理对象。 -
调用 Mapper 接口方法。
-
代理对象根据方法名,找到对应的 SQL 语句,并执行预编译。
-
将参数传入预编译的 SQL 语句。
-
执行 SQL,获取结果集。
-
Mybatis 将结果集映射到 Java 对象,并返回。
20. XML 和注解方式映射 SQL,有什么区别?
-
XML 方式:
-
优点:SQL 和 Java 代码分离,便于维护;支持更复杂的动态 SQL;支持更复杂的映射关系。
-
缺点:工作量大,需要维护两个文件。
-
-
注解方式:
-
优点:简单,不需要 XML 文件,适用于简单的 SQL。
-
缺点:不支持复杂的动态 SQL 和映射关系,代码和 SQL 耦合在一起。
-
总结 :通常在项目中,对于简单的 CRUD 和单表查询,可以使用注解。对于复杂的、需要动态 SQL 和联结查询的,则必须使用 XML。