2025年MyBatis面试题大全(精选120题)1~30题
1. 什么是MyBatis?它的核心组件有哪些?
答案:
MyBatis是一个半自动化的Java持久层框架,通过XML或注解配置SQL,将Java对象与数据库记录映射。核心组件包括:
- SqlSessionFactory:创建SqlSession的工厂,单例模式。
- SqlSession:执行SQL、管理事务的会话对象。
- Mapper接口:定义数据操作方法,与XML映射文件绑定。
- Configuration:存储全局配置和映射文件信息。
2. MyBatis与JDBC相比有哪些优势?
答案:
- 简化代码:避免手动处理连接、Statement、结果集解析。
- SQL与代码分离:通过XML或注解管理SQL,易于维护。
- 动态SQL:支持
<if>
,<foreach>
等标签灵活生成SQL。 - 缓存机制:内置一级(会话级)和二级(应用级)缓存。
- 集成Spring:通过
SqlSessionTemplate
实现线程安全。
3. MyBatis的一级缓存和二级缓存有什么区别?
答案:
特性 | 一级缓存 | 二级缓存 |
---|---|---|
作用域 | SqlSession级别 | SqlSessionFactory级别 |
生命周期 | 随会话创建/销毁 | 手动开启,应用全局生效 |
存储位置 | 内存(HashMap) | 可自定义(如Ehcache) |
默认状态 | 始终开启 | 需配置<cache> 标签启用 |
4. #{}
和${}
的区别是什么?
答案:
#{}
:预编译处理,防止SQL注入(如WHERE name = #{name}
)。${}
:直接字符串替换,存在注入风险(如动态表名${tableName}
)。
5. 如何解决实体类属性与数据库字段名不一致的问题?
答案:
- 方式1:SQL中定义别名(如
SELECT user_name AS userName
)。 - 方式2:使用
<resultMap>
映射(如<result column="user_name" property="userName"/>
)。
6. MyBatis的动态SQL有哪些标签?分别适用什么场景?
答案:
<if>
:条件判断(如WHERE name = #{name} if name != null
)。<choose>
/<when>
/<otherwise>
:多条件分支(类似switch-case)。<foreach>
:遍历集合(如IN (#{item})
批量插入)。<trim>
/<where>
/<set>
:自动处理SQL片段(如去除多余AND/OR)。
7. MyBatis如何执行批量插入?
答案:
- 方式1:使用
ExecutorType.BATCH
模式:SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH); try { UserMapper mapper = sqlSession.getMapper(UserMapper.class); for (User user : userList) { mapper.insert(user); } sqlSession.commit(); } finally { sqlSession.close(); }
- 方式2:XML中通过
<foreach>
拼接SQL(需数据库支持批量语法)。
8. MyBatis-Spring模块的作用是什么?
答案:
- 集成Spring事务管理(如
@Transactional
)。 - 通过
SqlSessionTemplate
解决线程安全问题。 - 支持注解方式注入Mapper(如
@Autowired private UserMapper userMapper;
)。
9. MyBatis的插件机制如何实现?
答案:
- 实现
Interceptor
接口,重写intercept()
方法。 - 使用
@Intercepts
和@Signature
注解标记拦截点(如Executor.update
)。 - 在
mybatis-config.xml
中配置插件:<plugins> <plugin interceptor="com.example.MyPlugin"/> </plugins>
10. MyBatis如何实现分页?
答案:
- 逻辑分页:使用
RowBounds
(内存分页,数据量大时性能差)。 - 物理分页:通过拦截器修改SQL(如PageHelper插件自动追加
LIMIT
)。
11. MyBatis的关联查询如何实现?
答案:
- 一对一:使用
<association>
(如用户与身份证)。 - 一对多:使用
<collection>
(如订单与商品列表)。 - 延迟加载:配置
fetchType="lazy"
,按需加载关联数据。
12. MyBatis的二级缓存如何配置?
答案:
- 在Mapper XML中添加
<cache/>
标签。 - 配置缓存参数(如过期时间、大小):
<cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>
- 实体类实现
Serializable
接口(若需分布式缓存)。
13. MyBatis的SqlSessionFactory为何是单例的?
答案:
- SqlSessionFactory是线程安全的,创建成本高(需解析配置文件)。
- 单例模式可避免重复加载配置,提升性能。
14. MyBatis如何防止SQL注入?
答案:
- 优先使用
#{}
预编译参数。 - 避免直接拼接
${}
,若必须使用需严格校验参数(如白名单过滤)。
15. MyBatis的ResultMap可以配置哪些属性?
答案:
column
:数据库字段名。property
:Java对象属性名。javaType
:属性类型(如java.util.Date
)。jdbcType
:JDBC类型(如VARCHAR
)。typeHandler
:自定义类型处理器。
16. MyBatis的Executor类型有哪些?如何选择?
答案:
- SIMPLE:默认执行器,每次操作创建新PreparedStatement。
- REUSE:复用PreparedStatement,减少编译开销。
- BATCH:批量执行SQL,适合导入数据场景。
17. MyBatis的日志集成方式有哪些?
答案:
- 在
mybatis-config.xml
中配置日志实现:<settings> <setting name="logImpl" value="SLF4J"/> </settings>
- 支持Log4j、Log4j2、JDK Logging等。
18. MyBatis的二级缓存为何默认关闭?
答案:
- 避免脏数据:多会话操作时,缓存一致性难以保证。
- 灵活性:开发者可根据场景选择Ehcache、Redis等第三方缓存。
19. MyBatis如何映射枚举类型?
答案:
- 使用
typeHandler
(如EnumOrdinalTypeHandler
按序号映射)。 - 自定义枚举处理器:
public class EnumNameTypeHandler extends BaseTypeHandler<StatusEnum> { // 实现setNonNullParameter、getNullableResult方法 }
20. MyBatis的XML映射文件能否跨命名空间调用?
答案:
- 可以,通过
<include refid="其他文件.sql片段ID"/>
复用SQL片段。
21. MyBatis的延迟加载原理是什么?
答案:
- 基于CGLIB或Javassist动态生成代理对象。
- 首次访问关联属性时触发查询(需配置
lazyLoadingEnabled=true
)。
22. MyBatis如何处理数据库方言?
答案:
- 通过
<databaseIdProvider>
配置多数据库支持:<databaseIdProvider type="DB_VENDOR"> <property name="MySQL" value="mysql"/> <property name="Oracle" value="oracle"/> </databaseIdProvider>
- 在SQL中通过
databaseId
属性区分(如<select id="..." databaseId="mysql">
)。
23. MyBatis的插件可以拦截哪些接口?
答案:
Executor
(执行SQL)。ParameterHandler
(处理参数)。ResultSetHandler
(处理结果集)。StatementHandler
(操作Statement)。
24. MyBatis的批量操作如何获取主键?
答案:
- 在插入语句中配置
useGeneratedKeys="true"
和keyProperty="id"
:<insert id="batchInsert" useGeneratedKeys="true" keyProperty="id"> INSERT INTO user (name) VALUES <foreach collection="list" item="item" separator=","> (#{item.name}) </foreach> </insert>
25. MyBatis的ResultMap与自动映射冲突如何解决?
答案:
- 设置
<setting name="autoMappingBehavior" value="PARTIAL"/>
,或显式关闭自动映射:<resultMap id="userMap" autoMapping="false"> <!-- 手动映射字段 --> </resultMap>
26. MyBatis的缓存淘汰策略有哪些?
答案:
- LRU(默认):最近最少使用。
- FIFO:先进先出。
- SOFT:基于软引用(内存敏感时回收)。
- WEAK:基于弱引用(GC时回收)。
27. MyBatis的XML映射文件是否支持继承?
答案:
- 支持,通过
<extends>
继承其他ResultMap:<resultMap id="detailMap" extends="baseMap"> <!-- 扩展字段映射 --> </resultMap>
28. MyBatis如何优化大数据量查询?
答案:
- 使用分页插件(如PageHelper)。
- 避免
SELECT *
,按需查询字段。 - 开启二级缓存减少数据库访问。
29. MyBatis的Mapper接口是否需要实现类?
答案:
- 不需要,MyBatis通过JDK动态代理生成接口实现类。
30. MyBatis的连接池如何配置?
答案:
- 在
mybatis-config.xml
中配置<dataSource>
:<dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://