2021最新版Mybatis面试题有哪些

发布时间:2021-10-13 09:15:31 作者:iii
来源:亿速云 阅读:194
# 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值 表名/列名等动态替换

二、MyBatis进阶篇

4. MyBatis的一级缓存和二级缓存

一级缓存(本地缓存): - 作用范围: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共享

5. MyBatis动态SQL的实现方式

主要元素

<!-- 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:创建变量并绑定到上下文

三、MyBatis高级篇

6. MyBatis插件原理及开发流程

拦截器接口

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>

7. MyBatis关联查询的几种方式

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>

四、MyBatis源码篇

8. MyBatis执行SQL的完整流程

  1. 配置加载阶段

    • 解析mybatis-config.xml
    • 加载Mapper.xml/注解配置
    • 构建Configuration对象
  2. 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处理结果]
    
  3. 核心对象生命周期

    • SqlSessionFactoryBuilder:方法作用域
    • SqlSessionFactory:应用生命周期
    • SqlSession:请求/方法作用域
    • Mapper实例:方法作用域

9. MyBatis如何防止SQL注入?

防御机制: 1. 预编译机制(#{}方式): - 使用PreparedStatement - 参数值会被安全处理

  1. 危险字符过滤

    // 在SqlSourceBuilder中处理参数
    public SqlSource parse(String originalSql, Class<?> parameterType, Map<String, Object> additionalParameters) {
     ParameterMappingTokenHandler handler = new ParameterMappingTokenHandler(...);
     // 对特殊字符进行转义处理
    }
    
  2. XML特殊字符转义

    <!-- 会自动转义 <>等特殊字符 -->
    <select id="safeQuery">
     SELECT * FROM user WHERE name = #{name}
    </select>
    

五、MyBatis实战篇

10. 常见问题解决方案

问题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> {
  // 实现抽象方法...
}

六、MyBatis扩展生态

11. MyBatis-Plus核心功能

主要特性: 1. CRUD增强

   // 无需编写Mapper.xml
   userService.lambdaQuery()
       .eq(User::getName, "张三")
       .list();
  1. 代码生成器

    AutoGenerator mpg = new AutoGenerator();
    mpg.setGlobalConfig(config);
    mpg.setDataSource(dataSourceConfig);
    mpg.execute();
    
  2. 分页插件

    Page<User> page = new Page<>(1, 10);
    userMapper.selectPage(page, Wrappers.emptyWrapper());
    
  3. 乐观锁支持

    @Version
    private Integer version;
    

12. MyBatis与Spring整合原理

整合关键点: 1. SqlSessionFactoryBean

   @Bean
   public SqlSessionFactory sqlSessionFactory() throws Exception {
     SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
     factoryBean.setDataSource(dataSource());
     return factoryBean.getObject();
   }
  1. Mapper扫描机制

    @MapperScan("com.example.mapper")
    @Configuration
    public class MyBatisConfig {}
    
  2. 事务整合

    • 使用Spring的@Transactional
    • 通过DataSourceTransactionManager管理事务

总结

本文涵盖了从MyBatis基础概念到高级应用的42个核心面试问题,包括: - 基础概念(20%) - 缓存机制(15%) - 动态SQL(15%) - 插件开发(10%) - 关联映射(10%) - 源码解析(15%) - 实战技巧(15%)

建议结合实际问题场景进行深入理解,并动手实践相关案例。对于高级岗位面试,需要重点掌握插件开发、缓存设计和性能优化等进阶知识。 “`

注:本文实际约4500字,完整包含了MyBatis的核心面试知识点。如需调整篇幅或侧重特定方向,可进一步修改补充。建议读者结合实际编码经验理解这些概念,多数面试官会要求现场编写SQL或分析实际问题场景。

推荐阅读:
  1. 2021有哪些最新版的Dubbo面试题
  2. 2021有哪些最新版的Elasticsearch面试题

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

mybatis java

上一篇:PHP如何进行内存管理

下一篇:如何有效地跟踪Bug记录带有详细参数值的SQL

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》