上周,实习生小钱问我:

“马哥,我们之前直接用 JdbcTemplate 连数据库,现在项目要换 MyBatis,感觉好复杂啊……有没有一个完整例子,从配置到增删改查都讲一遍?”

我笑了:“MyBatis 真的不复杂,复杂的是你没找到正确的入门姿势。”

今天,我就用 一个完整的用户管理项目,手把手教你:Spring Boot 如何整合 MyBatis,包含增删改查 + 分页查询复制粘贴就能跑通


🛠️ 一、准备工作(只需 2 分钟)

你需要:

  • MySQL(已按上篇文章配置好)
  • JDK 17(或 8/11)
  • IDEA
  • 已创建 testdb 数据库和 user 表(上篇文章已建)

💻 二、整合 MyBatis 的 5 个步骤(完整代码)

步骤 1:添加 MyBatis 依赖(pom.xml)

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    
    <!-- MyBatis Starter -->
    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>3.0.2</version>
    </dependency>
    
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
    </dependency>
</dependencies>

💡 注意

  • 版本号 3.0.2 适配 Spring Boot 3.x
  • 2.x 版本用 2.3.1(适配 Spring Boot 2.x)

步骤 2:配置 MyBatis(application.yml)

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/testdb?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver

mybatis:
  mapper-locations: classpath:mapper/*.xml  # 👈 指定 XML 映射文件位置
  type-aliases-package: com.example.mybatisdemo.entity  # 👈 实体类别名包
  configuration:
    map-underscore-to-camel-case: true  # 👈 数据库下划线字段自动映射到 Java 驼峰属性
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl  # 👈 开发时打印 SQL

🔍 关键配置解释

  • mapper-locations:告诉 MyBatis 去哪找 SQL 映射文件
  • type-aliases-package:简化 XML 中的类名书写
  • map-underscore-to-camel-caseuser_nameuserName(重要!)
  • log-impl:开发时能看到执行的 SQL,方便调试

步骤 3:创建实体类(entity/User.java)

package com.example.mybatisdemo.entity;

public class User {
    private Long id;
    private String name;
    private String email;

    // 构造函数(省略)
    public User() {}
    public User(String name, String email) {
        this.name = name;
        this.email = email;
    }

    // getter / setter(IDEA 生成)
    public Long getId() { return id; }
    public void setId(Long 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; }
}

步骤 4:创建 Mapper 接口(mapper/UserMapper.java)

package com.example.mybatisdemo.mapper;

import com.example.mybatisdemo.entity.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

import java.util.List;

@Mapper  // 👈 关键注解,让 Spring 管理这个接口
public interface UserMapper {

    // 查询所有用户
    List<User> findAll();

    // 根据 ID 查询用户
    User findById(@Param("id") Long id);

    // 新增用户
    int insert(User user);

    // 更新用户
    int update(User user);

    // 删除用户
    int deleteById(@Param("id") Long id);

    // 分页查询(后面实现)
    List<User> findByPage(@Param("offset") int offset, @Param("limit") int limit);

    // 获取总记录数(分页用)
    int countAll();
}

💡 @Param 注解
当方法参数多于 1 个,或在 XML 中需要引用参数名时,必须加 @Param
单个参数可不加(如 insert(User user)


步骤 5:创建 XML 映射文件(resources/mapper/UserMapper.xml)

<?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.mybatisdemo.mapper.UserMapper">

    <!-- 结果映射 -->
    <resultMap id="UserResultMap" type="User">
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <result property="email" column="email"/>
    </resultMap>

    <!-- 查询所有 -->
    <select id="findAll" resultMap="UserResultMap">
        SELECT id, name, email FROM user
    </select>

    <!-- 根据 ID 查询 -->
    <select id="findById" parameterType="java.lang.Long" resultMap="UserResultMap">
        SELECT id, name, email FROM user WHERE id = #{id}
    </select>

    <!-- 新增 -->
    <insert id="insert" parameterType="User" useGeneratedKeys="true" keyProperty="id">
        INSERT INTO user (name, email) VALUES (#{name}, #{email})
    </insert>

    <!-- 更新 -->
    <update id="update" parameterType="User">
        UPDATE user SET name = #{name}, email = #{email} WHERE id = #{id}
    </update>

    <!-- 删除 -->
    <delete id="deleteById" parameterType="java.lang.Long">
        DELETE FROM user WHERE id = #{id}
    </delete>

    <!-- 分页查询 -->
    <select id="findByPage" resultMap="UserResultMap">
        SELECT id, name, email FROM user LIMIT #{offset}, #{limit}
    </select>

    <!-- 总记录数 -->
    <select id="countAll" resultType="java.lang.Integer">
        SELECT COUNT(*) FROM user
    </select>

</mapper>

🔍 XML 关键点

  • namespace:必须是对应的 Mapper 接口全限定名
  • #{}:参数占位符(防 SQL 注入)
  • useGeneratedKeys="true":新增后返回自增主键
  • LIMIT #{offset}, #{limit}:MySQL 分页语法

步骤 6:创建 Service(service/UserService.java)

package com.example.mybatisdemo.service;

import com.example.mybatisdemo.entity.User;
import com.example.mybatisdemo.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class UserService {

    @Autowired
    private UserMapper userMapper;

    public List<User> getAllUsers() {
        return userMapper.findAll();
    }

    public User getUserById(Long id) {
        return userMapper.findById(id);
    }

    public User createUser(User user) {
        userMapper.insert(user);
        return user;
    }

    public User updateUser(User user) {
        userMapper.update(user);
        return user;
    }

    public void deleteUser(Long id) {
        userMapper.deleteById(id);
    }

    // 分页查询
    public List<User> getUsersByPage(int page, int size) {
        int offset = (page - 1) * size;
        return userMapper.findByPage(offset, size);
    }

    public int getTotalCount() {
        return userMapper.countAll();
    }
}

步骤 7:创建 Controller(controller/UserController.java)

package com.example.mybatisdemo.controller;

import com.example.mybatisdemo.entity.User;
import com.example.mybatisdemo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/api/users")
public class UserController {

    @Autowired
    private UserService userService;

    @GetMapping
    public List<User> getAllUsers() {
        return userService.getAllUsers();
    }

    @GetMapping("/{id}")
    public User getUserById(@PathVariable Long id) {
        return userService.getUserById(id);
    }

    @PostMapping
    public User createUser(@RequestBody User user) {
        return userService.createUser(user);
    }

    @PutMapping("/{id}")
    public User updateUser(@PathVariable Long id, @RequestBody User user) {
        user.setId(id);
        return userService.updateUser(user);
    }

    @DeleteMapping("/{id}")
    public String deleteUser(@PathVariable Long id) {
        userService.deleteUser(id);
        return "OK";
    }

    // 分页接口
    @GetMapping("/page")
    public Map<String, Object> getUsersByPage(
            @RequestParam(defaultValue = "1") int page,
            @RequestParam(defaultValue = "10") int size) {
        
        List<User> users = userService.getUsersByPage(page, size);
        int total = userService.getTotalCount();
        
        Map<String, Object> result = new HashMap<>();
        result.put("data", users);
        result.put("total", total);
        result.put("page", page);
        result.put("size", size);
        return result;
    }
}

▶️ 三、运行验证(30 秒搞定)

1. 启动项目

确保 MySQL 连接配置正确,启动 MybatisDemoApplication

2. 用 Postman 测试

新增用户:
POST http://localhost:8080/api/users
Content-Type: application/json

{
    "name": "张三",
    "email": "zhangsan@example.com"
}
查询所有:
GET http://localhost:8080/api/users
分页查询:
GET http://localhost:8080/api/users/page?page=1&size=5

✅ 控制台会打印 SQL 语句,看到 SELECTINSERT 等,说明成功!

四、Bonus:MyBatis 常见坑点

坑 1:Invalid bound statement

原因:XML 文件位置不对,或 namespace 写错
解决:检查 mapper-locations 路径,确保 XML 在 resources/mapper/

坑 2:@Param 忘记加

原因:多参数方法在 XML 中引用不到
解决:加 @Param("paramName")

坑 3:字段名不匹配

原因:数据库 user_name vs Java userName
解决:配置 map-underscore-to-camel-case: true


💬 六、写在最后

MyBatis 真的不难,难的是配置和参数映射的细节

记住三句话:

  • XML 文件必须在 resources/mapper/ 目录下
  • 多参数方法必须加 @Param
  • 下划线字段自动映射 map-underscore-to-camel-case

学会 MyBatis,你就掌握了 SQL 与 Java 对象之间的桥梁


互动时间
你用 MyBatis 遇到过什么奇怪的错误?是 XML 位置?还是参数映射?
欢迎评论区分享!点赞最高的送《MyBatis 实战速查手册》PDF!


下期预告
《Spring Boot 整合 Redis 缓存用户登录信息(含过期时间)》
👉 关注我,少走弯路,快速进阶!

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐