Appearance
MyBatis
MyBatis 是企业 Java 开发里非常常见的数据访问框架。
很多人对它的第一印象是“就是写 XML 的”,这个理解太窄了。
更贴近的说法是:MyBatis 在保留 SQL 控制力的前提下,把原始 JDBC 里重复、繁琐、容易出错的模板代码收起来。
这篇文章重点讲:
MyBatis到底是什么- 它解决什么问题
- 它和 JDBC、JPA 的区别是什么
- Mapper、
SqlSession、动态 SQL 这些词分别是什么意思 - 企业里为什么大量项目会选它
1. MyBatis 到底是什么
MyBatis 可以看成一个以 SQL 为中心的数据访问框架。
它不会像 ORM 那样尽量隐藏 SQL,而是让开发者继续掌控 SQL,同时帮你处理参数绑定、结果映射和执行流程。
所以它的核心风格可以直接记成:SQL 还是你写,但 JDBC 那些重复劳动它替你收掉。
2. 它主要解决什么问题
原始 JDBC 常见的问题包括:
- 连接、语句、结果集代码很多
- 参数绑定和结果集映射重复
- SQL 和 Java 代码容易缠在一起
- 动态查询写起来很别扭
MyBatis 要解决的核心问题就是:保留 SQL 控制力,同时降低 JDBC 模板代码成本。
3. 它和 JDBC、JPA 分别是什么关系
3.1 和 JDBC 的关系
JDBC 更底层,MyBatis 更高一层。
- JDBC 是数据库访问标准接口
- MyBatis 是建立在 JDBC 之上的框架
3.2 和 JPA 的关系
MyBatis 和 JPA 代表的是两种不同思路。
MyBatis更偏 SQL 驱动JPA更偏对象模型驱动
如果项目 SQL 很复杂、分页和报表很多、查询控制要求高,团队往往更倾向 MyBatis。
4. Mapper 到底是什么
Mapper 可以理解成把 Java 方法和 SQL 执行关联起来的一层接口抽象。
它解决的是:不要每次都手动写一堆 JDBC 调用,而是通过接口方法表达数据访问动作。
例如:
java
/**
* 最基础的用户 Mapper 接口示例。
*/
@Mapper
public interface UserMapper {
/**
* 按用户 ID 查询用户。
*
* @param id 用户主键 ID
* @return 查询到的用户对象
*/
User selectById(Long id);
/**
* 插入一条用户记录。
*
* @param user 待写入数据库的用户对象
* @return 受影响行数
*/
int insert(User user);
}这个接口本身不是“会自动查数据库”,而是 MyBatis 会把它和对应 SQL 映射关系关联起来。
5. XML 和注解两种写法怎么理解
MyBatis 最常见的两种写法通常是:
- XML 映射
- 注解映射
5.1 XML 映射
它更适合 SQL 比较复杂、动态条件多、需要较强可维护性时。
例如:
xml
<select id="selectById" resultType="com.example.User">
select id, name, age
from user
where id = #{id}
</select>5.2 注解映射
它更适合 SQL 简短直接、接口数量不多时。
例如:
java
/**
* 使用注解方式直接声明 SQL 的用户 Mapper。
*/
@Mapper
public interface UserMapper {
/**
* 按用户 ID 查询用户信息。
*
* @param id 用户主键 ID
* @return 查询到的用户对象
*/
@Select("select id, name, age from user where id = #{id}")
User selectById(Long id);
}- SQL 简单时,注解更轻
- SQL 复杂时,XML 更稳
6. #{} 和 ${} 有什么区别
这是 MyBatis 里非常关键的一组边界。
6.1 #{}
它更像预编译参数占位。
更安全,也更常用。
6.2 ${}
它更像字符串直接拼接。
灵活,但风险更大。
要注意的是:大多数普通参数绑定都应该优先用 #{}。
例如排序字段、表名这类动态拼接场景,才可能涉及 ${},而这时必须特别注意注入风险。
7. 结果映射到底在做什么
数据库查询出来的是结果集,业务里更常希望拿到 Java 对象。
结果映射 解决的就是:怎么把查询结果映射成 Java 对象。
最简单的情况可以直接靠字段同名映射; 更复杂时则会用到 resultMap。
例如:
xml
<resultMap id="userResultMap" type="com.example.User">
<id property="id" column="id"/>
<result property="userName" column="user_name"/>
</resultMap>
<select id="selectById" resultMap="userResultMap">
select id, user_name from user where id = #{id}
</select>8. 动态 SQL 到底解决什么问题
企业项目里查询条件经常不是固定的。
例如:
- 用户名可选
- 状态可选
- 时间区间可选
如果全部手写字符串拼接,很容易乱。
MyBatis 的动态 SQL 解决的是:根据条件动态生成 SQL,同时保持结构可维护。
例如:
xml
<select id="queryUsers" resultType="com.example.User">
select id, name, age
from user
<where>
<if test="name != null and name != ''">
and name = #{name}
</if>
<if test="age != null">
and age = #{age}
</if>
</where>
</select>9. SqlSession 是什么
SqlSession 可以理解成 MyBatis 执行 SQL、管理映射操作的一次会话入口。
它在底层很重要,但在 Spring Boot 整合场景下,很多时候不会直接手写操作它。
更常见的情况是:你直接注入 Mapper,Spring 和 MyBatis 帮你把底层会话协同好了。
10. MyBatis 和 Spring Boot 怎么整合
在企业项目里,比较常见的接入方式就是:
- 引入
mybatis-spring-boot-starter - 配置数据源
- 扫描 Mapper
- 编写接口和 XML / 注解 SQL
例如启动类或配置类里常见:
java
/**
* MyBatis 与 Spring Boot 整合时的启动入口。
*/
@SpringBootApplication
@MapperScan("com.example.mapper")
public class DemoApplication {
/**
* 启动当前应用,并让 Spring 扫描 Mapper 接口。
*
* @param args 命令行启动参数
*/
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}对应配置:
yaml
spring:
datasource:
url: jdbc:mysql://localhost:3306/demo
username: root
password: 123456
mybatis:
mapper-locations: classpath:/mapper/*.xml
type-aliases-package: com.example.domain11. MyBatis 常用注解和组件
| 注解 / 组件 | 作用 |
|---|---|
@Mapper | 标记 Mapper 接口 |
@MapperScan | 批量扫描 Mapper |
@Select / @Insert / @Update / @Delete | 注解方式定义 SQL |
SqlSession | MyBatis 会话入口 |
resultMap | 自定义结果映射 |
例如:
java
/**
* 订单表对应的数据访问接口。
*/
@Mapper
public interface OrderMapper {
/**
* 按订单 ID 更新订单状态。
*
* @param id 订单主键 ID
* @param status 目标状态值
* @return 受影响行数
*/
@Update("update orders set status = #{status} where id = #{id}")
int updateStatus(@Param("id") Long id, @Param("status") String status);
}12. 企业里为什么很多项目会选 MyBatis
比较常见的原因包括:
- SQL 控制力强
- 复杂查询表达直接
- 对 DBA、SQL 调优协作更友好
- 对报表、列表、统计场景很适合
所以它在很多中后台系统里非常常见。
13. 工程上最容易踩的几个坑
13.1 误区一:用了 MyBatis 就不需要理解数据库
不是。
索引、事务、锁、执行计划这些问题仍然要回到数据库本身。
13.2 误区二:${} 和 #{} 只是写法不同
不是。
它们在安全性和参数处理方式上差异非常大。
13.3 误区三:Mapper 方法写出来就一定高性能
性能最终还是取决于 SQL、索引、分页、批量策略和数据库设计。
14. 一句话总结
MyBatis 的核心价值,是在保留 SQL 控制力的前提下,把原始 JDBC 的模板代码、参数绑定和结果映射收口成更清晰的数据访问模型;而企业里真正要把它用好,关键仍然是 SQL 设计、数据库理解和与 Spring 事务链路的协同。