📌 摘要
在 Java 后端开发中,MyBatis 是一个非常流行且灵活的持久层框架。它不像 Hibernate 那样完全封装 SQL,而是提供了对 SQL 的精细控制能力,同时又具备 ORM(对象关系映射)的功能。
本文将带你从 MyBatis 基础语法 到 高级特性 全面掌握这一持久层利器,内容涵盖:
- MyBatis 简介与核心优势
- 快速入门示例(XML 和 注解方式)
- 映射文件详解(resultMap、动态SQL等)
- 与 Spring / Spring Boot 整合实战
- 性能优化技巧与最佳实践
- 常见面试题解析
适合初学者入门和中高级开发者提升技能。
- 🔥 MyBatis中文网地址
🎯 一、为什么选择 MyBatis?
✅ MyBatis 的特点:
特性 | 描述 |
---|---|
轻量级 | 无侵入性,无需继承特定类或实现接口 |
SQL 控制强 | 手写 SQL,便于性能调优 |
ORM 支持 | 自动将结果集映射为 Java 对象 |
动态 SQL | 提供 <if> 、<foreach> 等强大标签 |
可扩展性强 | 支持自定义类型处理器、插件机制 |
与主流框架兼容 | 完美支持 Spring、Spring Boot |
❗ 适用场景:
- 对 SQL 有较高要求,需要定制化查询
- 数据结构复杂、需频繁优化性能
- 不希望被 Hibernate 的“黑盒”束缚
- 企业项目中已有大量 SQL 脚本迁移需求
🧱 二、MyBatis 核心组件介绍
组件 | 描述 |
---|---|
SqlSessionFactoryBuilder | 构建 SqlSessionFactory 工厂对象 |
SqlSessionFactory | 创建 SqlSession 实例的核心工厂 |
SqlSession | 执行 SQL 语句并获取映射结果的主要接口 |
Mapper XML 文件 | 定义 SQL 语句和结果映射规则 |
Mapper 接口 | 通过接口绑定 XML 中的 SQL |
Configuration | 全局配置对象,包含数据源、事务管理器等信息 |
🚀 三、快速入门:搭建第一个 MyBatis 应用
✅ 开发环境准备:
- JDK 1.8+
- Maven 3.x
- MySQL 5.7+
- IDE(如 IntelliJ IDEA)
1. 添加依赖(Maven):
<!-- MyBatis -->
<dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.10</version>
</dependency><!-- MySQL驱动 -->
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.29</version>
</dependency>
2. 配置 mybatis-config.xml
:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><environments default="development"><environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="com.mysql.cj.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/test_db?useSSL=false&serverTimezone=UTC"/><property name="username" value="root"/><property name="password" value="123456"/></dataSource></environment></environments><mappers><mapper resource="mapper/UserMapper.xml"/></mappers>
</configuration>
3. 编写实体类 User.java
:
public class User {private Integer id;private String name;private String email;// Getter/Setter
}
4. Mapper 接口 UserMapper.java
:
public interface UserMapper {User selectById(Integer id);
}
5. Mapper XML 文件 UserMapper.xml
:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mapper.UserMapper"><select id="selectById" resultType="com.example.model.User">SELECT * FROM users WHERE id = #{id}</select>
</mapper>
6. 测试类 TestMyBatis.java
:
public class TestMyBatis {public static void main(String[] args) throws IOException {String resource = "mybatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);try (SqlSession session = sqlSessionFactory.openSession()) {UserMapper mapper = session.getMapper(UserMapper.class);User user = mapper.selectById(1);System.out.println(user.getName());}}
}
🛠️ 四、MyBatis 进阶功能详解
1. resultMap 结果映射
适用于字段名与属性名不一致的情况:
<resultMap id="userResultMap" type="User"><id property="id" column="user_id"/><result property="name" column="user_name"/><result property="email" column="email"/>
</resultMap><select id="selectAllUsers" resultMap="userResultMap">SELECT user_id, user_name, email FROM users
</select>
2. 动态 SQL
<if>
条件判断:
<select id="findUsers" parameterType="map" resultType="User">SELECT * FROM users<where><if test="name != null">AND name LIKE CONCAT('%', #{name}, '%')</if><if test="email != null">AND email = #{email}</if></where>
</select>
<choose>/<when>/<otherwise>
分支判断:
<choose><when test="name != null">AND name = #{name}</when><when test="email != null">AND email = #{email}</when><otherwise>AND status = 1</otherwise>
</choose>
<foreach>
遍历集合:
<delete id="deleteByIds">DELETE FROM users WHERE id IN<foreach collection="ids" item="id" open="(" separator="," close=")">#{id}</foreach>
</delete>
🔗 五、与 Spring / Spring Boot 整合实战
1. Spring Boot + MyBatis 快速整合
添加依赖:
<dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>3.0.3</version>
</dependency>
application.yml 配置:
spring:datasource:url: jdbc:mysql://localhost:3306/test_db?useSSL=false&serverTimezone=UTCusername: rootpassword: 123456driver-class-name: com.mysql.cj.jdbc.Drivermybatis:mapper-locations: classpath:mapper/*.xmltype-aliases-package: com.example.model
Mapper 接口自动注入:
@Mapper
public interface UserMapper {@Select("SELECT * FROM users WHERE id = #{id}")User selectById(Integer id);
}
🚀 六、MyBatis 高级特性与优化技巧
✅ 使用 PageHelper 分页插件:
<dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId><version>1.4.2</version>
</dependency>
使用示例:
PageHelper.startPage(1, 10);
List<User> users = userMapper.selectAll();
PageInfo<User> pageInfo = new PageInfo<>(users);
✅ 自定义 TypeHandler 类型转换器
public class BooleanTypeHandler implements TypeHandler<Boolean> {@Overridepublic void setNonNullParameter(PreparedStatement ps, int i, Boolean parameter, JdbcType jdbcType) {ps.setInt(i, parameter ? 1 : 0);}@Overridepublic Boolean getNullableResult(ResultSet rs, String columnName) throws SQLException {return rs.getInt(columnName) == 1;}
}
✅ 使用 MyBatis 插件(Interceptor)
可用于日志记录、分页、SQL 监控等。
@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
public class MyInterceptor implements Interceptor {@Overridepublic Object intercept(Invocation invocation) throws Throwable {// 前置处理逻辑System.out.println("Before executing SQL");// 执行原方法Object result = invocation.proceed();// 后置处理逻辑System.out.println("After executing SQL");return result;}@Overridepublic Object plugin(Object target) {return Plugin.wrap(target, this);}@Overridepublic void setProperties(Properties properties) {// 可以获取配置的属性}
}
💬 七、常见面试题解析
Q1: MyBatis 和 Hibernate 的区别?
答:Hibernate 是全自动 ORM 框架,屏蔽 SQL;MyBatis 是半自动 ORM,需手动编写 SQL,更灵活可控。
Q2: #{} 和 ${} 的区别?
答:#{}
是预编译占位符,防止 SQL 注入;${}
是字符串替换,存在注入风险。
Q3: 如何实现批量插入?
答:使用 <foreach>
标签拼接多条 INSERT 语句,或结合 JDBC 的批处理。
Q4: 如何防止 N+1 查询问题?
答:使用 <association>
或 <collection>
嵌套查询,并启用延迟加载(lazyLoadingEnabled)。
Q5: MyBatis 如何实现缓存?
答:一级缓存默认开启(SqlSession级别),二级缓存需手动配置(Mapper级别)。
💡 八、总结
通过本文的学习,你应该已经掌握了:
- MyBatis 的基本原理与使用方式
- 如何使用 XML 或注解方式进行 CRUD 操作
- 动态 SQL 的编写技巧
- resultMap 的使用与映射优化
- 与 Spring / Spring Boot 的整合方法
- 高级特性如分页、插件、自定义类型处理器
- 常见面试题解析
MyBatis 是 Java 持久层开发中的利器,既能保持灵活性,又能兼顾开发效率,是构建高性能后端系统的首选之一。
- 如果你在学习过程中遇到任何疑问,欢迎在评论区留言交流!
- 👍 如果你觉得这篇文章对你有帮助,别忘了点赞、收藏、转发哦!