MyBatis 到底能帮你省下多少写 SQL 的时间?

生产环境勿扰
2026-05-18 00:01
阅读 228

大家好,我是掘金上常写入门教程的全栈工程师。今天想和你聊聊 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&amp;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 中的 &amp; 是 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 入门,你已经掌握了最核心的部分。接下来可以:

  1. 学动态 SQL<if>, <foreach> 等标签,应对复杂查询
  2. 了解缓存机制:一级缓存(SqlSession 级)、二级缓存(Mapper 级)
  3. 整合 Spring Boot:实际项目几乎都用 MyBatis-Spring-Boot-Starter
  4. 尝试注解方式:小项目可用 @Select, @Insert 等直接写 SQL

📌 最后提醒:不要一上来就学 MyBatis-Plus!先掌握原生 MyBatis,才能理解高级封装的原理。


结语

写这篇教程,是因为我始终相信:好的技术分享,应该让新手少走弯路。MyBatis 虽然文档齐全,但对零基础者不够友好。希望这篇文章能成为你 Java 数据库开发的起点。

记住:所有复杂的框架,拆解后都是简单的概念组合。你已经迈出了第一步,接下来就是多写、多试、多 debug。

如果本文对你有帮助,欢迎在掘金点赞收藏。我是那个爱写入门教程的全栈工程师,我们下期再见!

评论 0

最热最新
暂无评论
匿名用户Lv.1
0
影响力
0
文章
0
粉丝