MyBatis 是一款灵活 ORM 框架,支持动态 SQL、对象映射及缓存机制,核心组件包括 SqlSessionFactory、Mapper 和 Executor,适用于复杂 SQL 优化、遗留数据库适配及高性能批量操作场景,强调对 SQL 的精细控制。
一、MyBatis 核心特性
1. SQL 与代码解耦
-
特性说明 MyBatis 通过 XML 或注解将 SQL 从 Java 代码中分离,便于维护和复用。
-
示例
<!-- UserMapper.xml --> <select id="selectUserById" resultType="User"> SELECT id, name, age FROM user WHERE id = #{id} </select>
2. 动态 SQL
-
特性说明 支持根据条件动态拼接 SQL,避免手动拼接字符串的繁琐和 SQL 注入风险。
-
核心标签
<if>,<choose>,<foreach>,<where>,<set>。 -
示例
<select id="findUsers" parameterType="map" resultType="User"> SELECT * FROM user <where> <if test="name != null"> AND name = #{name} </if> <if test="age != null"> AND age = #{age} </if> </where> </select>
3. 对象关系映射(ORM)
-
特性说明 通过
ResultMap将数据库字段与 Java 对象属性映射,支持复杂对象(嵌套对象、集合)。 -
示例
<resultMap id="userWithOrdersMap" type="User"> <id property="id" column="user_id"/> <result property="name" column="user_name"/> <!-- 一对多关联 --> <collection property="orders" ofType="Order"> <id property="orderId" column="order_id"/> <result property="amount" column="order_amount"/> </collection> </resultMap>
4. 接口绑定
-
特性说明 通过 Mapper 接口定义操作,MyBatis 自动生成实现类(基于动态代理),无需手动编写 DAO。
-
示例
public interface UserMapper { @Select("SELECT * FROM user WHERE id = #{id}") User selectUserById(int id); }
5. 缓存机制
-
一级缓存
- 默认开启,基于
SqlSession生命周期,同一会话中重复查询直接复用缓存。 - 失效场景:执行
insert/update/delete或调用clearCache()。
- 默认开启,基于
-
二级缓存
- 需手动开启,跨
SqlSession共享,适用于全局数据缓存。 - 配置方式:在 Mapper XML 中添加
<cache/>标签。 - 注意事项:实体类需实现
Serializable接口。
- 需手动开启,跨
二、MyBatis 核心组件
1. SqlSessionFactory
-
作用 全局单例工厂,用于创建
SqlSession。 -
配置方式
- 通过
mybatis-config.xml文件配置数据源、插件、类型处理器等。 - 与 Spring 集成时,使用
SqlSessionFactoryBean。
- 通过
-
示例
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="mapperLocations" value="classpath:mapper/*.xml"/> </bean>
2. SqlSession
-
作用 代表一次数据库会话,线程不安全,需确保及时关闭(通常通过
try-with-resources或 Spring 管理)。 -
核心方法
selectOne(),selectList():查询单条或多条数据。insert(),update(),delete():执行写操作。commit(),rollback():手动提交或回滚事务。
-
示例
try (SqlSession session = sqlSessionFactory.openSession()) { UserMapper mapper = session.getMapper(UserMapper.class); User user = mapper.selectUserById(1); }
3. Mapper 接口与 XML 映射文件
-
Mapper 接口 定义数据库操作方法,方法名与 XML 中的 SQL ID 对应。
-
XML 映射文件 编写 SQL 语句与映射规则,通过
<mapper>标签关联接口。 -
示例
<mapper namespace="com.example.mapper.UserMapper"> <select id="selectUserById" resultType="User"> SELECT * FROM user WHERE id = #{id} </select> </mapper>
4. Executor
-
作用 SQL 执行器,负责处理 SQL 请求,MyBatis 提供三种类型:
- SimpleExecutor:默认,每次执行创建新的
Statement。 - ReuseExecutor:复用
Statement,减少资源消耗。 - BatchExecutor:批量执行 SQL,提升写入性能。
- SimpleExecutor:默认,每次执行创建新的
-
配置方式 在全局配置中设置
defaultExecutorType:<settings> <setting name="defaultExecutorType" value="BATCH"/> </settings>
三、MyBatis 使用场景
1. 复杂 SQL 优化
-
场景说明 需要手动编写高效 SQL,如多表关联、子查询、窗口函数等。
-
示例
<select id="getSalesReport" resultType="map"> SELECT u.name, SUM(o.amount) AS total_amount, RANK() OVER (ORDER BY SUM(o.amount) DESC) AS rank FROM user u JOIN orders o ON u.id = o.user_id GROUP BY u.id </select>
2. 遗留数据库适配
-
场景说明 数据库表结构与对象模型不一致时,通过
ResultMap灵活映射。 -
示例
<resultMap id="legacyUserMap" type="User"> <id property="id" column="old_user_id"/> <result property="name" column="legacy_name"/> </resultMap>
3. 高性能批量操作
-
场景说明 使用
BatchExecutor执行批量插入或更新,减少数据库交互次数。 -
示例
try (SqlSession session = sqlSessionFactory.openSession(ExecutorType.BATCH)) { UserMapper mapper = session.getMapper(UserMapper.class); for (User user : userList) { mapper.insertUser(user); } session.commit(); }
4. 动态条件查询
-
场景说明 根据前端传入的条件动态生成 WHERE 子句,如电商平台的商品筛选。
-
示例
<select id="searchProducts" resultType="Product"> SELECT * FROM product <where> <if test="category != null"> AND category = #{category} </if> <if test="minPrice != null"> AND price >= #{minPrice} </if> <if test="maxPrice != null"> AND price <= #{maxPrice} </if> </where> </select>
四、解决的问题
MyBatis 是一个基于 Java 的持久层框架,主要解决了传统 JDBC 开发中的以下核心问题:
1. 简化 JDBC 繁琐操作
-
问题:直接使用 JDBC 需要手动处理连接获取、SQL 拼接、结果集映射、异常处理等大量样板代码,开发效率低下且易出错。
-
解决方案
:
- 自动管理连接:通过配置数据源,自动处理连接的获取和释放。
- SQL 与代码解耦:将 SQL 语句定义在 XML 或注解中,避免在 Java 代码中硬编码。
- 自动结果映射:将数据库查询结果自动映射到 Java 对象(POJO),无需手动遍历
ResultSet。
2. 提供灵活的对象关系映射(ORM)
-
问题:全自动 ORM 框架(如 Hibernate)生成的 SQL 不可控,复杂查询或优化困难。
-
解决方案
:
- 开发者控制 SQL:允许手动编写 SQL,确保查询效率和准确性。
- 动态 SQL:通过
<if>,<foreach>,<choose>等标签,根据条件动态生成 SQL,避免 Java 代码中的字符串拼接。 - 支持复杂映射:通过
<resultMap>定义字段与对象的映射关系,处理数据库字段名与 Java 属性名不一致的情况。
3. 实现 SQL 与业务逻辑分离
-
问题:JDBC 中 SQL 嵌入在 Java 代码中,导致代码臃肿、可读性差且难以维护。
-
解决方案
:
- XML 或注解配置:将 SQL 定义在独立的 XML 文件或注解中,业务逻辑聚焦在 Java 类中。
- 模块化设计:按功能划分 Mapper 接口和 XML 文件,提高代码可维护性。
4. 支持事务管理与集成
-
问题:JDBC 需要手动管理事务(提交、回滚),且难以与框架整合。
-
解决方案
:
- 与 Spring 无缝集成:通过
SqlSessionFactoryBean等组件,轻松整合 Spring 的事务管理(如@Transactional)。 - 声明式事务:简化事务边界的定义,避免侵入式代码。
- 与 Spring 无缝集成:通过
5. 提高开发效率与可维护性
-
问题:传统 JDBC 开发重复劳动多,团队协作成本高。
-
解决方案
:
- 代码生成工具:通过 MyBatis Generator 自动生成基础 CRUD 代码。
- 插件扩展:支持分页插件(PageHelper)、性能监控等工具,快速增强功能。
五、总结
- 核心特性:SQL 解耦、动态 SQL、灵活 ORM、接口绑定、缓存机制。
- 核心组件:
SqlSessionFactory(全局工厂)、SqlSession(会话)、Mapper(接口与 XML)、Executor(执行器)。 - 适用场景:复杂 SQL 优化、遗留系统适配、高性能批量操作、动态查询需求。
优势:对 SQL 的完全控制权,适合需要精细化操作数据库的场景; 劣势:相比全自动 ORM(如 Hibernate),需编写更多 SQL 和映射配置。