MyBatis 到底能帮你省下多少写 SQL 的时间?
大家好,我是掘金上常写入门教程的全栈工程师。今天想和你聊聊 MyBatis ——这个我刚毕业时花了整整三天才跑通第一个 Demo 的 Java 持久层框架。
为什么我要写这篇《MyBatis基础教程:Java持久层框架入门》?因为当初我学的时候,网上的资料要么太老(还在用 XML 配一大堆配置),要么直接跳进高级特性,新手根本看不懂。所以今天这篇文章,我会用「问题解决思路」的方式,带你从零开始,亲手写出第一个 MyBatis 程序,彻底搞懂它到底解决了什么问题。
本文为 v0 技术分享 系列的第一篇,目标是:让完全没碰过数据库操作的 Java 新手,也能在 1 小时内跑通一个完整的 CRUD 示例。
一、MyBatis 是什么?它解决了什么痛点?
先别急着装环境!我们先搞清楚:为什么需要 MyBatis?
假设你现在会写 Java,也学过一点 MySQL,想做一个“用户管理系统”。最原始的做法是什么?
// 伪代码:纯 JDBC 写法
Connection conn = DriverManager.getConnection(url, user, pwd);
PreparedStatement ps = conn.prepareStatement("SELECT * FROM user WHERE id = ?");
ps.setInt(1, 1001);
ResultSet rs = ps.executeQuery();
User user = new User();
user.setId(rs.getInt("id"));
user.setName(rs.getString("name"));
// ... 还要处理关闭资源、异常、重复代码 ...
问题来了:
- 每次查数据都要写一堆样板代码(连接、预编译、结果集映射)
- SQL 和 Java 代码混在一起,难维护
- 改个字段名,Java 和 SQL 都要改
MyBatis 的核心价值就是:把 SQL 从 Java 代码中解耦出来,自动完成对象和数据库记录的映射(ORM),但又不像 Hibernate 那样“全自动”——它让你保留对 SQL 的完全控制权。
简单说:你只管写 SQL,MyBatis 帮你执行并转成 Java 对象。
二、环境准备:5 分钟搭好开发环境
💡 提示:我建议你用 IntelliJ IDEA + Maven + MySQL 8.0+,这是目前最主流的组合。
1. 安装必要软件
| 软件 | 版本要求 | 说明 |
|---|---|---|
| JDK | 8 或 11 | 推荐 Oracle JDK 或 OpenJDK |
| Maven | 3.6+ | 用于依赖管理 |
| MySQL | 5.7+(推荐 8.0) | 数据库服务器 |
| IDEA | 2020.3+ | 社区版即可 |
2. 创建 Maven 项目
打开 IDEA → New Project → Maven → 不选模板 → 输入 GroupId(如 com.example)、ArtifactId(如 mybatis-demo)
3. 添加核心依赖(pom.xml)
<dependencies>
<!-- MyBatis 核心 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.13</version>
</dependency>
<!-- MySQL 驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
<!-- 单元测试(可选但推荐) -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
</dependencies>
⚠️ 注意:MySQL 8.0 需要用
8.x驱动,否则会连不上!
4. 初始化数据库
CREATE DATABASE mybatis_demo;
USE mybatis_demo;
CREATE TABLE user (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
email VARCHAR(100)
);
INSERT INTO user (name, email) VALUES
('张三', 'zhangsan@example.com'),
('李四', 'lisi@example.com');
三、核心概念:MyBatis 的三大支柱
MyBatis 虽然灵活,但核心就三个东西:
1. SqlSessionFactory:SQL 工厂
- 相当于 MyBatis 的“总控中心”
- 通过配置文件或代码构建
- 用来创建 SqlSession
2. SqlSession:会话对象
- 代表一次数据库会话
- 可以执行 SQL、提交事务、获取 Mapper
3. Mapper:接口 + SQL 映射
- 接口:定义方法(如
User findById(int id)) - XML 文件 或 注解:写对应的 SQL
🌟 关键理解:Mapper 接口不需要实现类!MyBatis 在运行时动态生成实现。
四、实战:手把手写一个用户查询功能
现在,我们一步步实现 根据 ID 查询用户。
步骤 1:创建实体类 User.java
package com.example.model;
public class User {
private Integer id;
private String name;
private String email;
// 必须要有无参构造(MyBatis 反射需要)
public User() {}
// getter / setter 省略(IDEA 可自动生成)
public Integer getId() { return id; }
public void setId(Integer id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
}
步骤 2:编写 MyBatis 配置文件 mybatis-config.xml
在 src/main/resources 下新建:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"https://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/mybatis_demo?useSSL=false&serverTimezone=UTC"/>
<property name="username" value="root"/>
<property name="password" value="你的密码"/>
</dataSource>
</environment>
</environments>
<!-- 注册 Mapper XML 文件 -->
<mappers>
<mapper resource="mapper/UserMapper.xml"/>
</mappers>
</configuration>
🔑 注意 URL 中的
&是 XML 转义,实际是&。时区设为 UTC 避免警告。
步骤 3:创建 Mapper 接口
package com.example.mapper;
import com.example.model.User;
public interface UserMapper {
User findById(int id);
}
步骤 4:编写 Mapper XML 文件
在 src/main/resources/mapper/ 下新建 UserMapper.xml:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mapper.UserMapper">
<select id="findById" resultType="com.example.model.User">
SELECT id, name, email FROM user WHERE id = #{id}
</select>
</mapper>
✅ 关键点:
namespace必须是接口的全限定名id必须和接口方法名一致#{id}是参数占位符(防 SQL 注入)
步骤 5:编写测试代码
package com.example;
import com.example.mapper.UserMapper;
import com.example.model.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import java.io.InputStream;
public class MyBatisTest {
@Test
public void testFindById() throws Exception {
// 1. 读取配置文件
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
// 2. 构建 SqlSessionFactory
SqlSessionFactory sqlSessionFactory =
new SqlSessionFactoryBuilder().build(inputStream);
// 3. 打开 SqlSession
try (SqlSession session = sqlSessionFactory.openSession()) {
// 4. 获取 Mapper
UserMapper mapper = session.getMapper(UserMapper.class);
// 5. 调用方法
User user = mapper.findById(1);
System.out.println(user.getName()); // 输出:张三
}
}
}
🎉 恭喜!如果控制台输出了“张三”,说明你的第一个 MyBatis 程序成功了!
五、扩展:实现增删改(CRUD 全覆盖)
有了查询基础,其他操作也很简单。我们快速过一遍。
1. 插入用户
// UserMapper.java
int insertUser(User user);
<!-- UserMapper.xml -->
<insert id="insertUser" useGeneratedKeys="true" keyProperty="id">
INSERT INTO user (name, email) VALUES (#{name}, #{email})
</insert>
🔍
useGeneratedKeys="true"表示使用数据库自增主键,并回填到user.id
2. 更新用户
int updateUser(User user);
<update id="updateUser">
UPDATE user SET name=#{name}, email=#{email} WHERE id=#{id}
</update>
3. 删除用户
int deleteUser(int id);
<delete id="deleteUser">
DELETE FROM user WHERE id = #{id}
</delete>
💡 所有操作返回值都是 受影响的行数(int),可用于判断是否成功。
六、新手常见问题 & 避坑指南
我当初踩过的坑,你别再踩了!
❌ 问题 1:ClassNotFoundException: com.mysql.cj.jdbc.Driver
原因:MySQL 8.0 驱动类名变了(旧版是 com.mysql.jdbc.Driver)
解决:确认 pom.xml 中驱动版本 ≥ 8.0,配置文件中 driver 写 com.mysql.cj.jdbc.Driver
❌ 问题 2:Invalid bound statement (not found)
原因:Mapper 接口和 XML 没匹配上
检查点:
- XML 的
namespace是否等于接口全名? - 方法名
id是否和接口方法一致? - XML 文件是否被 Maven 打包?(resources 目录下)
❌ 问题 3:中文乱码
解决:在 JDBC URL 后加上字符集参数:
?useUnicode=true&characterEncoding=UTF-8
❌ 问题 4:实体类属性和数据库字段名不一致
比如数据库是 user_name,Java 是 userName
方案:用 resultMap 显式映射
<resultMap id="UserResultMap" type="User">
<id property="id" column="id"/>
<result property="userName" column="user_name"/>
</resultMap>
<select id="findById" resultMap="UserResultMap">
SELECT id, user_name FROM user WHERE id = #{id}
</select>
七、下一步学习建议
MyBatis 的世界远不止这些,但作为 v0 入门,你已经掌握了最核心的部分。接下来可以:
- 学动态 SQL:
<if>,<foreach>等标签,应对复杂查询 - 了解缓存机制:一级缓存(SqlSession 级)、二级缓存(Mapper 级)
- 整合 Spring Boot:实际项目几乎都用 MyBatis-Spring-Boot-Starter
- 尝试注解方式:小项目可用
@Select,@Insert等直接写 SQL
📌 最后提醒:不要一上来就学 MyBatis-Plus!先掌握原生 MyBatis,才能理解高级封装的原理。
结语
写这篇教程,是因为我始终相信:好的技术分享,应该让新手少走弯路。MyBatis 虽然文档齐全,但对零基础者不够友好。希望这篇文章能成为你 Java 数据库开发的起点。
记住:所有复杂的框架,拆解后都是简单的概念组合。你已经迈出了第一步,接下来就是多写、多试、多 debug。
如果本文对你有帮助,欢迎在掘金点赞收藏。我是那个爱写入门教程的全栈工程师,我们下期再见!

评论 0