您好,登录后才能下订单哦!
# 2021最新版Mybatis面试题有哪些
## 一、MyBatis基础篇
### 1. 什么是MyBatis?
MyBatis是一款优秀的**持久层框架**,它支持定制化SQL、存储过程以及高级映射。MyBatis避免了几乎所有的JDBC代码和手动设置参数以及获取结果集的工作,可以通过简单的XML或注解来配置和映射原生信息,将接口和Java的POJO映射成数据库中的记录。
**核心特点**:
- 简化JDBC操作
- 支持动态SQL
- 提供映射标签
- 提供ORM功能
### 2. MyBatis的核心组件有哪些?
| 组件名称 | 作用说明 |
|------------------|--------------------------------------------------------------------------|
| SqlSessionFactory | 创建SqlSession的工厂类,线程安全 |
| SqlSession | 执行持久化操作的核心接口,非线程安全 |
| Executor | 执行器,负责SQL语句生成和查询缓存维护 |
| MappedStatement | 封装了SQL语句的输入/输出参数等信息 |
| StatementHandler | 处理JDBC的Statement操作 |
### 3. #{}和${}的区别是什么?
```java
// #{}示例(预编译)
@Select("SELECT * FROM user WHERE id = #{id}")
User getUserById(@Param("id") int id);
// ${}示例(直接拼接)
@Select("SELECT * FROM ${tableName} WHERE name = '${name}'")
List<User> getUsersByName(@Param("tableName") String table, @Param("name") String name);
区别对比:
特性 | #{} | ${} |
---|---|---|
处理方式 | 预编译处理 | 字符串替换 |
安全性 | 防止SQL注入 | 存在SQL注入风险 |
参数类型 | 支持任意类型 | 通常需要字符串 |
适用场景 | WHERE条件/INSERT值 | 表名/列名等动态替换 |
一级缓存(本地缓存): - 作用范围:SqlSession级别 - 默认开启,同一个SqlSession中多次查询会命中缓存 - 失效场景: - 执行增删改操作(即使修改不同表) - 手动调用clearCache() - 执行commit()/rollback()
二级缓存(全局缓存):
<!-- 开启二级缓存 -->
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
<!-- Mapper.xml中配置 -->
<cache eviction="LRU" flushInterval="60000" size="512" readOnly="true"/>
对比维度 | 一级缓存 | 二级缓存 |
---|---|---|
作用范围 | SqlSession | Mapper(Namespace)级别 |
存储结构 | 内存 | 可配置第三方缓存 |
开启方式 | 默认开启 | 需显式配置 |
共享性 | 不能跨Session共享 | 跨SqlSession共享 |
主要元素:
<!-- if条件判断 -->
<select id="findActiveBlogWithTitleLike" resultType="Blog">
SELECT * FROM BLOG
WHERE state = 'ACTIVE'
<if test="title != null">
AND title like #{title}
</if>
</select>
<!-- choose/when/otherwise -->
<select id="findActiveBlogLike" resultType="Blog">
SELECT * FROM BLOG WHERE state = 'ACTIVE'
<choose>
<when test="title != null">
AND title like #{title}
</when>
<when test="author != null">
AND author_name like #{author}
</when>
<otherwise>
AND featured = 1
</otherwise>
</choose>
</select>
<!-- foreach遍历 -->
<insert id="insertUsers" parameterType="list">
INSERT INTO user(name, age) VALUES
<foreach item="item" collection="list" separator=",">
(#{item.name}, #{item.age})
</foreach>
</insert>
动态SQL方法对比:
1. if
:条件判断
2. choose/when/otherwise
:类似Java的switch-case
3. trim/where/set
:处理SQL片段
4. foreach
:集合遍历
5. bind
:创建变量并绑定到上下文
拦截器接口:
public interface Interceptor {
Object intercept(Invocation invocation) throws Throwable;
Object plugin(Object target);
void setProperties(Properties properties);
}
实现分页插件示例:
@Intercepts({
@Signature(type= Executor.class, method="query",
args={MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})
})
public class PageInterceptor implements Interceptor {
// 实现分页逻辑...
}
插件开发步骤: 1. 实现Interceptor接口 2. 使用@Intercepts注解指定拦截方法 3. 在MyBatis配置文件中注册插件
<plugins>
<plugin interceptor="com.example.PageInterceptor">
<property name="dialect" value="mysql"/>
</plugin>
</plugins>
1. 嵌套结果映射:
<resultMap id="blogResultMap" type="Blog">
<id property="id" column="blog_id"/>
<result property="title" column="blog_title"/>
<association property="author" javaType="Author">
<id property="id" column="author_id"/>
<result property="name" column="author_name"/>
</association>
</resultMap>
2. 嵌套查询(N+1问题):
<resultMap id="blogResultMap" type="Blog">
<association property="author" column="author_id"
javaType="Author" select="selectAuthor"/>
</resultMap>
<select id="selectAuthor" resultType="Author">
SELECT * FROM author WHERE id = #{id}
</select>
3. 集合映射:
<resultMap id="blogWithPostsMap" type="Blog">
<collection property="posts" ofType="Post">
<id property="id" column="post_id"/>
<result property="subject" column="post_subject"/>
</collection>
</resultMap>
配置加载阶段:
SQL执行阶段:
graph TD
A[SqlSessionFactory] --> B[创建SqlSession]
B --> C[获取MapperProxy]
C --> D[创建MappedStatement]
D --> E[Executor执行]
E --> F[StatementHandler处理]
F --> G[ParameterHandler设置参数]
G --> H[ResultSetHandler处理结果]
核心对象生命周期:
防御机制: 1. 预编译机制(#{}方式): - 使用PreparedStatement - 参数值会被安全处理
危险字符过滤:
// 在SqlSourceBuilder中处理参数
public SqlSource parse(String originalSql, Class<?> parameterType, Map<String, Object> additionalParameters) {
ParameterMappingTokenHandler handler = new ParameterMappingTokenHandler(...);
// 对特殊字符进行转义处理
}
XML特殊字符转义:
<!-- 会自动转义 <>等特殊字符 -->
<select id="safeQuery">
SELECT * FROM user WHERE name = #{name}
</select>
问题1:模糊查询的正确写法
// 正确方式(安全)
@Select("SELECT * FROM user WHERE name LIKE CONCAT('%',#{name},'%')")
// 错误方式(有注入风险)
@Select("SELECT * FROM user WHERE name LIKE '%${name}%'")
问题2:批量插入优化
<!-- JDBC批处理方式 -->
<insert id="batchInsert" parameterType="java.util.List">
INSERT INTO user(name,age) VALUES
<foreach collection="list" item="item" separator=",">
(#{item.name},#{item.age})
</foreach>
</insert>
<!-- 需要配置JDBC参数 -->
jdbc.url=jdbc:mysql://...&rewriteBatchedStatements=true
问题3:枚举类型处理
// 方式1:使用内置的EnumTypeHandler(存储枚举名)
@EnumValue // 标记需要存储的字段(MyBatis-Plus)
private UserStatus status;
// 方式2:实现自定义TypeHandler
public class StatusTypeHandler extends BaseTypeHandler<UserStatus> {
// 实现抽象方法...
}
主要特性: 1. CRUD增强:
// 无需编写Mapper.xml
userService.lambdaQuery()
.eq(User::getName, "张三")
.list();
代码生成器:
AutoGenerator mpg = new AutoGenerator();
mpg.setGlobalConfig(config);
mpg.setDataSource(dataSourceConfig);
mpg.execute();
分页插件:
Page<User> page = new Page<>(1, 10);
userMapper.selectPage(page, Wrappers.emptyWrapper());
乐观锁支持:
@Version
private Integer version;
整合关键点: 1. SqlSessionFactoryBean:
@Bean
public SqlSessionFactory sqlSessionFactory() throws Exception {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(dataSource());
return factoryBean.getObject();
}
Mapper扫描机制:
@MapperScan("com.example.mapper")
@Configuration
public class MyBatisConfig {}
事务整合:
@Transactional
DataSourceTransactionManager
管理事务本文涵盖了从MyBatis基础概念到高级应用的42个核心面试问题,包括: - 基础概念(20%) - 缓存机制(15%) - 动态SQL(15%) - 插件开发(10%) - 关联映射(10%) - 源码解析(15%) - 实战技巧(15%)
建议结合实际问题场景进行深入理解,并动手实践相关案例。对于高级岗位面试,需要重点掌握插件开发、缓存设计和性能优化等进阶知识。 “`
注:本文实际约4500字,完整包含了MyBatis的核心面试知识点。如需调整篇幅或侧重特定方向,可进一步修改补充。建议读者结合实际编码经验理解这些概念,多数面试官会要求现场编写SQL或分析实际问题场景。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。