MyBatis 到底怎么用?零基础也能上手的 Java 持久层入门指南

App程序员
2026-02-23 19:08
阅读 1376

大家好,我是小陈,一名 211 高校的计算机专业研究生。平时喜欢写技术博客,尤其热衷于帮刚入行的同学少走弯路。今天这篇教程,就是源于我当初学 MyBatis 时踩过的坑——文档太官方、概念太抽象、代码示例又不完整。所以我想用最直白的语言、最贴近实战的方式,带你从零开始掌握 MyBatis。

你可能会问:为什么现在还要学 MyBatis? 毕竟 Spring Boot + JPA / Hibernate 听起来更“现代”。但现实是:国内绝大多数企业级 Java 项目(尤其是金融、政务系统)仍在广泛使用 MyBatis。它轻量、灵活、SQL 可控,非常适合对数据库操作有精细要求的场景。

顺便提一句,虽然本文聚焦 Java,但如果你也接触 Go(比如用 GORM),会发现 ORM 思想是相通的。而最近热门的 RAG(检索增强生成)系统中,后端往往也需要高效读写数据库——MyBatis 就是这类数据持久化的可靠选择之一。


一、MyBatis 是什么?能解决什么问题?

简单说:MyBatis 是一个 Java 的持久层框架。它的核心任务就一个:帮你把 Java 对象和数据库记录互相转换

想象一下,没有框架时你要做什么:

  • 手动加载 JDBC 驱动
  • 写 Connection、Statement、ResultSet
  • 处理 SQL 注入风险
  • 手动把 ResultSet 一行行转成 Java 对象(俗称 “ORM”)
  • 还要记得关资源、处理异常……

这些重复劳动不仅繁琐,还容易出错。MyBatis 把这些脏活累活封装好了,你只需要:

  1. 写 SQL(对,你没看错,MyBatis 不隐藏 SQL!)
  2. 定义 Java 类(POJO)
  3. 配置映射关系

剩下的,交给 MyBatis。

💡 我当初学的时候以为 ORM 框架都要像 Hibernate 那样“全自动”,结果发现 MyBatis 的“半自动”反而更适合业务复杂、SQL 需要调优的场景。


二、环境准备:5 分钟搭好开发环境

我们用最经典的组合:Java + Maven + MySQL + MyBatis

1. 前置条件

确保你已安装:

  • JDK 8 或以上(推荐 JDK 17)
  • Maven 3.6+
  • MySQL 5.7+(或 MariaDB)

2. 创建 Maven 项目

在 IDE(如 IntelliJ IDEA)中新建一个 Maven 项目,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>

3. 初始化数据库

创建一个测试库 mybatis_demo,并建一张用户表:

CREATE DATABASE mybatis_demo;
USE mybatis_demo;

CREATE TABLE user (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(50) NOT NULL,
    email VARCHAR(100)
);

插入几条测试数据:

INSERT INTO user (name, email) VALUES 
('张三', 'zhangsan@example.com'),
('李四', 'lisi@example.com');

三、核心概念:3 个文件搞懂 MyBatis

MyBatis 的工作流程可以简化为:

Java 程序 → 调用 Mapper 接口 → MyBatis 执行对应 SQL → 返回 Java 对象

你需要理解以下三个关键部分:

1. 实体类(POJO)

代表数据库中的一行数据。例如 User.java

public class User {
    private Integer id;
    private String name;
    private String email;
    
    // 必须有无参构造(MyBatis 反射需要)
    public User() {}
    
    // getter 和 setter(略,IDE 可自动生成)
    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. Mapper 接口

定义你能对数据库执行哪些操作。例如 UserMapper.java

public interface UserMapper {
    List<User> findAll();          // 查询所有用户
    User findById(Integer id);     // 根据 ID 查询
    void insert(User user);        // 插入新用户
    void update(User user);        // 更新用户
    void deleteById(Integer id);   // 删除用户
}

⚠️ 注意:这是一个接口!不需要实现类。MyBatis 会在运行时动态生成实现。

3. SQL 映射文件(XML)

告诉 MyBatis 每个接口方法对应哪条 SQL。创建 UserMapper.xml(通常放在 resources/mapper/ 下):

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.example.mapper.UserMapper">
  
  <select id="findAll" resultType="com.example.model.User">
    SELECT * FROM user
  </select>
  
  <select id="findById" parameterType="int" resultType="com.example.model.User">
    SELECT * FROM user WHERE id = #{id}
  </select>
  
  <insert id="insert" parameterType="com.example.model.User">
    INSERT INTO user (name, email) VALUES (#{name}, #{email})
  </insert>
  
  <update id="update" parameterType="com.example.model.User">
    UPDATE user SET name = #{name}, email = #{email} WHERE id = #{id}
  </update>
  
  <delete id="deleteById" parameterType="int">
    DELETE FROM user WHERE id = #{id}
  </delete>
  
</mapper>

关键点解释:

  • namespace 必须是 Mapper 接口的全限定名
  • id 必须和接口方法名一致
  • #{} 是 MyBatis 的占位符,会自动防 SQL 注入

四、全局配置:让 MyBatis 知道去哪连数据库

创建 mybatis-config.xml(放在 resources 根目录):

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
  PUBLIC "-//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/mybatis_demo?useSSL=false&amp;serverTimezone=UTC"/>
        <property name="username" value="root"/>
        <property name="password" value="your_password"/>
      </dataSource>
    </environment>
  </environments>

  <mappers>
    <mapper resource="mapper/UserMapper.xml"/>
  </mappers>
</configuration>

🔒 安全提示:生产环境中密码不要硬编码!可用环境变量或配置中心。


五、实战:写一个完整的增删改查程序

现在,我们把前面所有东西串起来。

1. 工具类:获取 SqlSession

public class MyBatisUtil {
    private static SqlSessionFactory sqlSessionFactory;
    
    static {
        try {
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            throw new RuntimeException("初始化 MyBatis 失败", e);
        }
    }
    
    public static SqlSession getSession() {
        return sqlSessionFactory.openSession();
    }
}

2. 测试主程序

public class Main {
    public static void main(String[] args) {
        try (SqlSession session = MyBatisUtil.getSession()) {
            UserMapper mapper = session.getMapper(UserMapper.class);
            
            // 1. 查询所有
            System.out.println("=== 查询所有用户 ===");
            List<User> users = mapper.findAll();
            users.forEach(u -> System.out.println(u.getName() + " - " + u.getEmail()));
            
            // 2. 新增用户
            User newUser = new User();
            newUser.setName("王五");
            newUser.setEmail("wangwu@example.com");
            mapper.insert(newUser);
            session.commit(); // 注意:增删改需要手动提交!
            
            // 3. 再次查询验证
            System.out.println("\n=== 新增后再次查询 ===");
            users = mapper.findAll();
            users.forEach(u -> System.out.println(u.getId() + ": " + u.getName()));
        }
    }
}

运行结果类似:

=== 查询所有用户 ===
张三 - zhangsan@example.com
李四 - lisi@example.com

=== 新增后再次查询 ===
1: 张三
2: 李四
3: 王五

✅ 关键提醒:MyBatis 默认事务不自动提交!insert/update/delete 后必须调用 session.commit(),否则数据不会写入数据库。


六、新手常见问题与避坑指南

❓ 问题 1:Mapper method was not found 错误

原因:XML 文件中的 namespaceid 和接口方法不匹配。
解决:检查三点:

  • XML 的 namespace 是否为接口全路径?
  • 方法名是否和 id 一致?
  • XML 文件是否被正确加载?(检查 mybatis-config.xml 中的 <mappers> 配置)

❓ 问题 2:中文乱码

原因:数据库连接未指定字符集。
解决:在 JDBC URL 中加上 &characterEncoding=utf8

<property name="url" value="jdbc:mysql://...&characterEncoding=utf8"/>

❓ 问题 3:属性名和字段名不一致(如 userName vs user_name

方案:使用 <resultMap> 显式映射:

<resultMap id="UserMap" type="User">
    <id property="id" column="id"/>
    <result property="userName" column="user_name"/>
    <result property="email" column="email"/>
</resultMap>

<select id="findById" resultMap="UserMap">
    SELECT id, user_name, email FROM user WHERE id = #{id}
</select>

❓ 问题 4:能否不用 XML,纯注解?

可以!MyBatis 支持注解方式(适合简单 SQL):

public interface UserMapper {
    @Select("SELECT * FROM user")
    List<User> findAll();
    
    @Insert("INSERT INTO user(name, email) VALUES(#{name}, #{email})")
    void insert(User user);
}

但复杂 SQL(如多表关联、动态 SQL)仍推荐 XML。


七、学习建议:下一步该学什么?

  1. 掌握动态 SQL<if><foreach><choose> 等标签是 MyBatis 的精华。
  2. 集成 Spring Boot:实际项目几乎都用 mybatis-spring-boot-starter,省去手动管理 SqlSession。
  3. 了解缓存机制:MyBatis 有一级缓存(SqlSession 级)和二级缓存(Mapper 级)。
  4. 对比其他 ORM:试试 Hibernate(全自动)或 Go 的 GORM,理解不同设计哲学。
  5. 结合 RAG 场景思考:如果你在做基于向量数据库的检索增强生成系统,MyBatis 可用于管理元数据(如文档 ID、来源、更新时间等结构化信息)。

🌟 最后送大家一句话:不要怕写 SQL。MyBatis 的优势恰恰在于让你掌控 SQL,而不是被框架束缚。当你能写出高效的 SQL,再配合 MyBatis 的便利性,你就真正掌握了数据持久化的主动权。

希望这篇教程能帮你顺利入门 MyBatis。如果觉得有用,欢迎关注我的博客,后续我会更新《MyBatis 动态 SQL 实战》和《MyBatis + Spring Boot 最佳实践》系列!


作者:小陈 | 211 计算机研二在读 | 技术博客:xxx.com

评论 0

最热最新
暂无评论
App程序员Lv.1
0
影响力
0
文章
0
粉丝