java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > SpringBoot MyBatisPlus 单表CRUD

Spring Boot + MyBatisPlus快速实现单表CRUD的示例

作者:码客日记

本文主要介绍了Spring Boot + MyBatisPlus快速实现单表CRUD的示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

在Spring Boot项目开发中,单表CRUD(新增Create、查询Retrieve、修改Update、删除Delete)是最基础、最常用的操作。传统MyBatis实现CRUD需要编写大量XML映射文件和SQL语句,繁琐且易出错;而MyBatis-Plus(MP)作为MyBatis的增强工具,通过内置接口和注解,实现了单表CRUD的“零XML、零SQL”极简开发,新手也能快速上手。

本文基于「Spring Boot + MyBatis-Plus + MySQL」技术栈,全程贴合实战,从环境准备、项目搭建、代码编写到测试验证,一步步教你快速实现单表CRUD,同时梳理高频踩坑点和最佳实践,确保你不仅能实现功能,还能规范编码、规避问题,适配日常开发场景。

前置说明:本文默认你已掌握「Spring Boot + MyBatis-Plus 连接MySQL」的基础操作(数据库连接、依赖导入),若未掌握,可先完成数据库连接配置,再继续本文内容(文末附基础连接补充)。

一、前置准备(极简版,快速适配)

确保本地环境和项目依赖满足要求,避免版本不兼容导致功能异常,直接照搬配置即可。

1. 环境要求

2. 核心依赖(pom.xml)

项目中需引入以下核心依赖,若已创建项目,核对并补充即可;若新建项目,IDEA勾选对应选项自动导入。

<!-- Spring Boot 核心启动器 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- MyBatis-Plus 启动器(核心,内置MyBatis,无需单独引入) -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.3.1</version>
</dependency>
<!-- MySQL 8.0 驱动 -->
<dependency>
    <groupId>com.mysql</groupId>
    <artifactId>mysql-connector-j</artifactId>
    <scope>runtime</scope>
</dependency>
<!-- Lombok(简化实体类,无需写get/set、toString) -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>
<!-- 测试依赖(用于测试CRUD功能) -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

3. 数据库与表准备

提前创建测试数据库和单表,本文以「用户表(user)」为例,执行以下SQL语句(MySQL客户端中运行),确保表结构和字段与后续实体类对应。

-- 1. 创建数据库(名称:mp_demo,可自定义,需与yml配置一致)
CREATE DATABASE IF NOT EXISTS mp_demo 
DEFAULT CHARACTER SET utf8mb4 
DEFAULT COLLATE utf8mb4_general_ci;
-- 2. 切换到目标数据库
USE mp_demo;
-- 3. 创建用户表(user),单表CRUD测试用
CREATE TABLE IF NOT EXISTS `user` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID(自增)',
  `name` varchar(30) NOT NULL COMMENT '用户姓名',
  `age` int(11) DEFAULT NULL COMMENT '用户年龄',
  `email` varchar(50) DEFAULT NULL COMMENT '用户邮箱',
  `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';

4. 核心配置(application.yml)

编写数据库连接配置和MyBatis-Plus基础配置,重点修改数据库名称、账号、密码,其余配置直接复用,确保CRUD操作能正常关联数据库。

# 服务器配置(可选,避免端口冲突)
server:
  port: 8081
  servlet:
    context-path: /crud-demo
# 数据库连接配置(核心,必须修改)
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver  # MySQL 8.0 驱动类
    url: jdbc:mysql://localhost:3306/mp_demo?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=false
    username: root  # 你的MySQL账号(默认root)
    password: 123456  # 你的MySQL密码
# MyBatis-Plus 配置(简化CRUD关键)
mybatis-plus:
  type-aliases-package: com.example.cruddemo.entity  # 实体类包路径(修改为你的包名)
  mapper-locations: classpath:mapper/**/*.xml  # 自定义SQL的XML路径(本文暂用不到,预留)
  configuration:
    map-underscore-to-camel-case: true  # 开启下划线转驼峰(数据库create_time → 实体类createTime)
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl  # 开启SQL日志打印(便于调试,查看执行的SQL)
  global-config:
    db-config:
      table-prefix:  # 表前缀(若表名有前缀,如mp_user,此处填mp_,本文无前缀,留空)
      id-type: AUTO  # 主键自增策略(与数据库表id自增对应)

避坑提醒:若使用MySQL 5.7,需将驱动类改为「com.mysql.jdbc.Driver」,并删除url中的「serverTimezone=GMT%2B8」配置,驱动依赖替换为mysql-connector-java:5.1.47。

二、核心代码编写(零XML、零SQL,快速实现CRUD)

MyBatis-Plus的核心优势的是「BaseMapper接口」和「IService接口」,两者都内置了完整的单表CRUD方法,无需手动编写SQL。本文分别演示两种方式(新手优先掌握BaseMapper,简化开发;IService适合复杂业务场景)。

项目包结构规范(必遵循,避免扫描失败):

com.example.cruddemo  # 项目根包
├── CrudDemoApplication.java  # 启动类
├── entity  # 实体类包(对应数据库表)
│   └── User.java
├── mapper  # Mapper接口包(继承BaseMapper)
│   └── UserMapper.java
├── service  # 服务层包(继承IService,可选)
│   ├── UserService.java
│   └── impl
│       └── UserServiceImpl.java
└── controller  # 控制层包(编写接口,测试CRUD,可选)
    └── UserController.java

1. 第一步:编写实体类(Entity)

实体类与数据库表一一对应,通过Lombok简化代码,通过MyBatis-Plus注解指定表名、主键策略等(若实体类名与表名一致、字段名与数据库字段一致,部分注解可省略)。

package com.example.cruddemo.entity;

import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import java.util.Date;

/**
 * 用户实体类,对应数据库user表
 */
@Data  // Lombok注解,自动生成get/set、toString、equals等方法
@TableName("user")  // 指定对应数据库表名(实体类名与表名一致时,可省略)
public class User {

    /**
     * 主键ID,自增
     * @TableId:指定主键,type=IdType.AUTO 对应数据库自增策略
     */
    @TableId(type = IdType.AUTO)
    private Long id;

    /**
     * 用户名,对应数据库name字段
     * 字段名与数据库一致,无需额外注解
     */
    private String name;

    /**
     * 年龄,对应数据库age字段
     */
    private Integer age;

    /**
     * 邮箱,对应数据库email字段
     */
    private String email;

    /**
     * 创建时间,对应数据库create_time字段
     * @TableField:指定数据库字段名(下划线转驼峰可省略,此处用于演示)
     * fill = FieldFill.INSERT:插入时自动填充时间(无需手动设置)
     */
    @TableField(value = "create_time", fill = FieldFill.INSERT)
    private Date createTime;

    /**
     * 更新时间,对应数据库update_time字段
     * fill = FieldFill.INSERT_UPDATE:插入和更新时自动填充时间
     */
    @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
    private Date updateTime;
}

2. 第二步:时间自动填充配置(可选,优化体验)

实体类中createTime和updateTime字段配置了「自动填充」,需编写填充处理器,实现插入/更新时自动填充当前时间,无需手动设置字段值。

package com.example.cruddemo.config;

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.util.Date;

/**
 * MyBatis-Plus 时间自动填充处理器
 */
@Component  // 交给Spring管理,必须添加该注解
public class MyMetaObjectHandler implements MetaObjectHandler {

    // 插入时自动填充
    @Override
    public void insertFill(MetaObject metaObject) {
        // 填充createTime和updateTime字段,值为当前时间
        strictInsertFill(metaObject, "createTime", Date.class, new Date());
        strictInsertFill(metaObject, "updateTime", Date.class, new Date());
    }

    // 更新时自动填充
    @Override
    public void updateFill(MetaObject metaObject) {
        // 只填充updateTime字段,值为当前时间
        strictUpdateFill(metaObject, "updateTime", Date.class, new Date());
    }
}

3. 方式1:基于BaseMapper实现CRUD(新手首选)

BaseMapper是MyBatis-Plus提供的基础Mapper接口,内置了完整的单表CRUD方法(insert、selectById、selectList、updateById、deleteById等),只需让自定义Mapper接口继承BaseMapper,无需编写任何方法,即可直接使用。

3.1 编写Mapper接口

package com.example.cruddemo.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.cruddemo.entity.User;
import org.apache.ibatis.annotations.Mapper;

/**
 * UserMapper接口,继承BaseMapper,实现单表CRUD
 * @Mapper:标记为MyBatis-Plus的Mapper接口,让Spring Boot自动扫描
 */
@Mapper
public interface UserMapper extends BaseMapper<User> {
    // 无需编写任何方法!BaseMapper已内置所有单表CRUD方法
}

3.2 启动类添加Mapper扫描(关键避坑)

打开项目启动类,添加@MapperScan注解,指定Mapper接口所在的包路径,否则Spring Boot无法扫描到Mapper接口,会导致注入失败。

package com.example.cruddemo;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@MapperScan("com.example.cruddemo.mapper")  // 扫描Mapper接口包(修改为你的包名)
public class CrudDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(CrudDemoApplication.class, args);
    }

}

3.3 BaseMapper核心CRUD方法(常用,必记)

BaseMapper内置了数十种方法,以下是单表CRUD最常用的方法,直接调用即可,无需写SQL:

方法名功能描述示例
insert(T entity)新增一条数据(返回影响行数)userMapper.insert(user);
selectById(Serializable id)根据主键ID查询一条数据userMapper.selectById(1L);
selectList(QueryWrapper queryWrapper)查询所有数据(可加条件)userMapper.selectList(null);(查询所有)
updateById(T entity)根据主键ID修改数据(非null字段才修改)userMapper.updateById(user);
deleteById(Serializable id)根据主键ID删除一条数据userMapper.deleteById(1L);
selectCount(QueryWrapper queryWrapper)统计数据条数(可加条件)userMapper.selectCount(null);(统计所有)

4. 方式2:基于IService实现CRUD(适合业务层开发)

IService是MyBatis-Plus提供的服务层接口,基于BaseMapper封装,提供了更丰富的CRUD方法(如批量操作、分页查询),还支持自定义业务逻辑,适合实际开发中的服务层编写(推荐项目开发使用)。

4.1 编写Service接口(继承IService)

package com.example.cruddemo.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.example.cruddemo.entity.User;

/**
 * UserService接口,继承IService,封装CRUD方法和业务逻辑
 */
public interface UserService extends IService<User> {
    // 此处可添加自定义业务方法(如根据姓名查询用户),基础CRUD方法IService已内置
}

4.2 编写Service实现类(继承ServiceImpl)

package com.example.cruddemo.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.cruddemo.entity.User;
import com.example.cruddemo.mapper.UserMapper;
import com.example.cruddemo.service.UserService;
import org.springframework.stereotype.Service;

/**
 * Service实现类,继承ServiceImpl,关联Mapper和Entity
 * @Service:标记为Spring服务层组件,交给Spring管理
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    // 基础CRUD方法无需编写,IService/ServiceImpl已内置
    // 示例:自定义业务方法(根据姓名查询用户,后续可扩展)
    /*
    public User selectByName(String name) {
        // 用QueryWrapper构建查询条件(下文会演示)
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("name", name);
        return baseMapper.selectOne(queryWrapper);
    }
    */
}

4.3 IService核心CRUD方法(常用)

IService在BaseMapper基础上做了增强,新增了批量操作、分页等方法,常用方法如下:

三、测试验证(两种方式,确保CRUD功能正常)

本文通过「Spring Boot测试类」直接测试CRUD功能,无需编写接口,简单高效;后续也可通过控制层编写接口,用Postman测试(文末附控制层示例)。

1. 测试BaseMapper方式(新手优先)

在test目录下,找到默认的测试类,注入UserMapper,编写测试方法,逐一验证CRUD功能。

package com.example.cruddemo;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.cruddemo.entity.User;
import com.example.cruddemo.mapper.UserMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;

@SpringBootTest  // 标记为Spring Boot测试类,启动Spring容器
class CrudDemoApplicationTests {

    // 自动注入UserMapper(Spring扫描@Mapper注解后,自动创建实例)
    @Autowired
    private UserMapper userMapper;

    /**
     * 测试1:新增用户(Create)
     */
    @Test
    void testInsert() {
        // 创建User对象,无需设置id(自增)、createTime、updateTime(自动填充)
        User user = new User();
        user.setName("张三");
        user.setAge(22);
        user.setEmail("zhangsan@163.com");

        // 调用BaseMapper的insert方法,新增数据
        int rows = userMapper.insert(user);
        System.out.println("新增成功,影响行数:" + rows);
        System.out.println("新增用户ID:" + user.getId());  // 新增后,自增ID会自动回显
    }

    /**
     * 测试2:根据ID查询用户(Retrieve)
     */
    @Test
    void testSelectById() {
        // 调用selectById方法,根据ID查询(ID为新增时回显的ID,可修改为自己的)
        User user = userMapper.selectById(1L);
        System.out.println("查询到的用户信息:" + user);
    }

    /**
     * 测试3:查询所有用户 + 条件查询(Retrieve)
     */
    @Test
    void testSelectList() {
        // 1. 查询所有用户(无条件,queryWrapper传null)
        List<User> allUser = userMapper.selectList(null);
        System.out.println("所有用户:" + allUser);

        // 2. 条件查询(示例:查询年龄>20的用户)
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.gt("age", 20);  // gt表示“大于”,eq表示“等于”,lt表示“小于”
        List<User> userList = userMapper.selectList(queryWrapper);
        System.out.println("年龄大于20的用户:" + userList);
    }

    /**
     * 测试4:根据ID修改用户(Update)
     */
    @Test
    void testUpdateById() {
        // 1. 先查询要修改的用户(确保用户存在)
        User user = userMapper.selectById(1L);
        // 2. 修改用户信息(仅修改非null字段)
        user.setAge(23);  // 修改年龄
        user.setEmail("zhangsan_update@163.com");  // 修改邮箱

        // 3. 调用updateById方法,修改数据
        int rows = userMapper.updateById(user);
        System.out.println("修改成功,影响行数:" + rows);
    }

    /**
     * 测试5:根据ID删除用户(Delete)
     */
    @Test
    void testDeleteById() {
        // 调用deleteById方法,根据ID删除(ID为要删除的用户ID,谨慎操作)
        int rows = userMapper.deleteById(1L);
        System.out.println("删除成功,影响行数:" + rows);
    }
}

2. 测试IService方式(服务层测试)

注入UserService,测试IService内置的CRUD方法,用法与BaseMapper类似,更贴合实际业务开发。

package com.example.cruddemo;

import com.example.cruddemo.entity.User;
import com.example.cruddemo.service.UserService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;

@SpringBootTest
class UserServiceTest {

    // 自动注入UserService(@Service注解标记,Spring自动管理)
    @Autowired
    private UserService userService;

    // 测试新增
    @Test
    void testSave() {
        User user = new User();
        user.setName("李四");
        user.setAge(25);
        user.setEmail("lisi@163.com");
        boolean success = userService.save(user);  // IService返回boolean,更直观
        System.out.println("新增是否成功:" + success);
    }

    // 测试查询所有
    @Test
    void testList() {
        List<User> userList = userService.list();
        System.out.println("所有用户:" + userList);
    }

    // 测试修改
    @Test
    void testUpdateById() {
        User user = new User();
        user.setId(2L);  // 必须设置ID,否则无法修改
        user.setAge(26);
        boolean success = userService.updateById(user);
        System.out.println("修改是否成功:" + success);
    }

    // 测试删除
    @Test
    void testRemoveById() {
        boolean success = userService.removeById(2L);
        System.out.println("删除是否成功:" + success);
    }

    // 测试批量新增(IService增强方法)
    @Test
    void testSaveBatch() {
        User user1 = new User();
        user1.setName("王五");
        user1.setAge(28);
        user1.setEmail("wangwu@163.com");

        User user2 = new User();
        user2.setName("赵六");
        user2.setAge(30);
        user2.setEmail("zhaoliu@163.com");

        List<User> userList = List.of(user1, user2);
        boolean success = userService.saveBatch(userList);
        System.out.println("批量新增是否成功:" + success);
    }
}

3. 测试成功标志

四、可选扩展:编写控制层接口(Postman测试)

实际开发中,CRUD功能通常通过接口对外提供,这里编写简单的RESTful接口,用Postman测试,贴合真实开发场景。

package com.example.cruddemo.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.cruddemo.entity.User;
import com.example.cruddemo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;

/**
 * 用户控制层,编写CRUD接口
 * @RestController:等同于@Controller + @ResponseBody,返回JSON数据
 * @RequestMapping:接口统一前缀
 */
@RestController
@RequestMapping("/api/user")
public class UserController {

    @Autowired
    private UserService userService;

    // 1. 新增用户(POST请求)
    @PostMapping("/add")
    public String addUser(@RequestBody User user) {
        boolean success = userService.save(user);
        return success ? "新增成功" : "新增失败";
    }

    // 2. 根据ID查询用户(GET请求)
    @GetMapping("/{id}")
    public User getUserById(@PathVariable Long id) {
        return userService.getById(id);
    }

    // 3. 查询所有用户(GET请求)
    @GetMapping("/list")
    public List<User> getUserList() {
        return userService.list();
    }

    // 4. 根据ID修改用户(PUT请求)
    @PutMapping("/update")
    public String updateUser(@RequestBody User user) {
        boolean success = userService.updateById(user);
        return success ? "修改成功" : "修改失败";
    }

    // 5. 根据ID删除用户(DELETE请求)
    @DeleteMapping("/{id}")
    public String deleteUser(@PathVariable Long id) {
        boolean success = userService.removeById(id);
        return success ? "删除成功" : "删除失败";
    }

    // 6. 条件查询(示例:根据姓名查询)
    @GetMapping("/list/name")
    public List<User> getUserByName(@RequestParam String name) {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("name", name);
        return userService.list(queryWrapper);
    }
}

接口测试方法:启动项目,打开Postman,根据接口请求方式(POST/PUT/GET/DELETE),输入接口地址(如 http://localhost:8081/crud-demo/api/user/add),传递参数,即可测试CRUD功能。

五、高频踩坑点汇总(新手必看,规避90%问题)

整理了新手实现单表CRUD时最常遇到的6个问题,每个问题附上根因和解决方案,遇到报错直接对照排查,快速解决。

踩坑1:Mapper注入失败(No qualifying bean of type ‘xxxMapper’ available)

✅ 报错原因:启动类未添加@MapperScan注解,或注解中的包路径错误;Mapper接口未添加@Mapper注解。

✅ 解决方案:启动类添加@MapperScan(“com.example.cruddemo.mapper”);确保Mapper接口添加@Mapper注解;核对包路径,确保一致。

踩坑2:新增/修改后,时间字段未自动填充

✅ 报错原因:未编写时间自动填充处理器(MyMetaObjectHandler);处理器未添加@Component注解,未被Spring管理;实体类字段的@TableField(fill = …)配置错误。

✅ 解决方案:编写MyMetaObjectHandler类,添加@Component注解;核对实体类字段的fill属性,insert对应INSERT,update对应INSERT_UPDATE。

踩坑3:修改数据无效,无报错

✅ 报错原因:修改时未设置实体类的id字段(MyBatis-Plus根据id修改);实体类所有字段为null,无修改内容;数据库表主键不是id,或主键策略配置错误。

✅ 解决方案:修改时必须设置实体类的id;确保至少有一个非null字段需要修改;核对yml中mybatis-plus.global-config.db-config.id-type配置,与数据库主键策略一致。

踩坑4:条件查询无结果,SQL日志显示条件错误

✅ 报错原因:QueryWrapper构建条件时,字段名与数据库字段不一致;未开启下划线转驼峰配置,导致字段匹配失败(如createTime对应create_time)。

✅ 解决方案:QueryWrapper中使用数据库字段名(如name、age),而非实体类驼峰名;确保yml中开启map-underscore-to-camel-case: true。

踩坑5:Service注入失败(No qualifying bean of type ‘xxxService’ available)

✅ 报错原因:Service实现类未添加@Service注解;Service接口未继承IService,或实现类未继承ServiceImpl。

✅ 解决方案:Service实现类添加@Service注解;确保UserService继承IService,UserServiceImpl继承ServiceImpl<UserMapper, User>。

踩坑6:SQL日志不打印,无法调试

✅ 报错原因:未开启MyBatis-Plus的SQL日志打印配置;log-impl配置路径错误。

✅ 解决方案:在yml的mybatis-plus.configuration中,添加log-impl: org.apache.ibatis.logging.stdout.StdOutImpl。

六、补充:BaseMapper vs IService 选择建议

很多新手会纠结两种方式的选择,结合实际开发场景,给出明确建议,避免选型困惑:

七、总结

Spring Boot + MyBatis-Plus 实现单表CRUD的核心,就是“复用MyBatis-Plus内置接口”,无需编写XML和SQL,极大简化了开发流程,核心步骤可总结为3步:

本文覆盖了新手实现单表CRUD的全流程,从基础配置到进阶用法,从测试验证到踩坑排查,贴合实战场景,新手只需跟着步骤操作,就能快速上手。后续可基于此基础,学习MyBatis-Plus的高级特性(条件构造器、分页插件、自动生成代码),进一步提高开发效率。

若遇到其他问题,可对照本文踩坑点排查,或留言交流,助力你快速搞定单表CRUD开发!

到此这篇关于Spring Boot + MyBatisPlus快速实现单表CRUD的示例的文章就介绍到这了,更多相关SpringBoot MyBatisPlus 单表CRUD内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文