SpringBoot3 | MyBatis-Plus 搞定宠物管理:从0到1实现增删改查

SpringBoot3 + MyBatis-Plus 搞定宠物管理:从0到1实现增删改查

日常开发中,只要涉及到数据库操作,"增删改查"几乎是绕不开的基础场景。比如宠物门店需要管理宠物信息,手动写SQL不仅繁琐,还容易出错------有没有更高效的方式?

今天就以宠物信息管理为例,聊聊如何用SpringBoot3整合MyBatis-Plus,零冗余实现基础的CRUD操作。整个过程我会拆解得足够细,哪怕是刚接触SpringBoot的同学,也能跟着一步步做出来。

先明确核心目标

我们要实现的功能很清晰:

  • 新增宠物信息(姓名、品种、年龄)
  • 根据ID查询单条宠物信息
  • 查询所有宠物信息
  • 根据ID修改宠物信息
  • 根据ID删除宠物信息

对应的实体类Pet已经给定,我们基于这个基础展开。

第一步:环境准备

1.1 基础依赖(Maven)

SpringBoot3要求JDK版本至少为17,先确保环境符合。然后在pom.xml中引入核心依赖:

xml 复制代码
<!-- SpringBoot父工程 -->
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.2.0</version>
    <relativePath/>
</parent>

<dependencies>
    <!-- SpringWeb:提供Web接口能力 -->
    <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.5</version>
    </dependency>

    <!-- MySQL驱动:连接MySQL数据库 -->
    <dependency>
        <groupId>com.mysql</groupId>
        <artifactId>mysql-connector-j</artifactId>
        <scope>runtime</scope>
    </dependency>

    <!-- Lombok:简化实体类代码(省去getter/setter等) -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>

    <!-- 测试依赖(可选) -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

1.2 数据库准备

创建MySQL数据库(比如命名为pet_manage),并新建pet表,字段和实体类对应:

sql 复制代码
CREATE TABLE `pet` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '宠物ID',
  `name` varchar(50) DEFAULT NULL COMMENT '宠物名称',
  `breed` varchar(50) DEFAULT NULL COMMENT '宠物品种',
  `age` int(11) DEFAULT NULL COMMENT '宠物年龄',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

第二步:核心配置

src/main/resources下创建application.yml,配置数据库连接和MyBatis-Plus基础参数:

yaml 复制代码
spring:
  # 数据库连接配置
  datasource:
    url: jdbc:mysql://localhost:3306/pet_manage?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
    username: root  # 替换为你的MySQL用户名
    password: 123456  # 替换为你的MySQL密码
    driver-class-name: com.mysql.cj.jdbc.Driver

# MyBatis-Plus配置
mybatis-plus:
  # 实体类别名包(简化XML中的类名引用)
  type-aliases-package: com.example.petmanage.entity
  configuration:
    # 打印SQL日志(开发阶段方便调试)
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    # 下划线转驼峰(数据库字段pet_name → 实体类petName)
    map-underscore-to-camel-case: true

第三步:代码实现

3.1 实体类(Pet)

按照要求创建实体类,放在com.example.petmanage.entity包下:

java 复制代码
package com.example.petmanage.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data // 自动生成getter、setter、toString、hashCode、equals
@NoArgsConstructor // 无参构造器
@AllArgsConstructor // 全参构造器
public class Pet {
    private Long id;         // 宠物ID(唯一标识)
    private String name;     // 宠物名称
    private String breed;    // 宠物品种(如"金毛"、"布偶猫")
    private Integer age;     // 宠物年龄(单位:岁)
}

3.2 Mapper层(核心:复用MyBatis-Plus的BaseMapper)

MyBatis-Plus的核心优势之一就是封装了基础CRUD的Mapper方法,我们只需要创建接口继承BaseMapper即可,无需手动写SQL。

创建PetMapper接口,放在com.example.petmanage.mapper包下:

java 复制代码
package com.example.petmanage.mapper;

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

// 注解标记为MyBatis的Mapper接口,SpringBoot会自动扫描
@Mapper
public interface PetMapper extends BaseMapper<Pet> {
    // 无需写任何方法!BaseMapper已经封装了insert、selectById、updateById、deleteById、selectList等方法
}

3.3 Service层(封装业务逻辑,可选但推荐)

实际开发中,我们会在Service层封装业务逻辑,MyBatis-Plus也提供了IService/ServiceImpl简化Service层开发。

3.3.1 Service接口
java 复制代码
package com.example.petmanage.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.example.petmanage.entity.Pet;

public interface PetService extends IService<Pet> {
    // 基础CRUD方法已由IService封装,如需自定义业务方法可在此扩展
}
3.3.2 Service实现类
java 复制代码
package com.example.petmanage.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.petmanage.entity.Pet;
import com.example.petmanage.mapper.PetMapper;
import com.example.petmanage.service.PetService;
import org.springframework.stereotype.Service;

@Service
public class PetServiceImpl extends ServiceImpl<PetMapper, Pet> implements PetService {
    // 无需写基础CRUD实现!ServiceImpl已基于PetMapper实现了IService的所有方法
}

3.4 Controller层(提供Web接口)

创建PetController,暴露HTTP接口供前端调用,放在com.example.petmanage.controller包下:

java 复制代码
package com.example.petmanage.controller;

import com.example.petmanage.common.ResultCode;
import com.example.petmanage.entity.Pet;
import com.example.petmanage.common.R;
import com.example.petmanage.service.PetService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/pet")
public class PetController {

    @Autowired
    private PetService petService;

    /**
     * 新增宠物信息
     * @param pet 宠物信息(JSON格式)
     * @return 统一返回结果
     */
    @PostMapping("/add")
    public R<Boolean> addPet(@RequestBody Pet pet) {
        // 参数校验:名称和品种不能为空,年龄需大于0
        if (pet == null || !StringUtils.hasText(pet.getName()) || !StringUtils.hasText(pet.getBreed())) {
            return R.error(ResultCode.PARAM_ERROR);
        }
        if (pet.getAge() != null && pet.getAge() <= 0) {
            return R.error(400, "宠物年龄必须大于0");
        }
        // 执行新增操作
        boolean saveFlag = petService.save(pet);
        if (saveFlag) {
            return R.success(true);
        } else {
            return R.error(ResultCode.ERROR);
        }
    }

    /**
     * 根据ID查询宠物信息
     * @param id 宠物ID
     * @return 统一返回结果(包含宠物信息)
     */
    @GetMapping("/{id}")
    public R<Pet> getPetById(@PathVariable Long id) {
        // 参数校验:ID不能为空且大于0
        if (id == null || id <= 0) {
            return R.error(ResultCode.PARAM_ERROR);
        }
        // 执行查询操作
        Pet pet = petService.getById(id);
        if (pet != null) {
            return R.success(pet);
        } else {
            return R.error(ResultCode.DATA_NOT_FOUND);
        }
    }

    /**
     * 查询所有宠物信息
     * @return 统一返回结果(包含宠物列表)
     */
    @GetMapping("/list")
    public R<List<Pet>> getAllPets() {
        List<Pet> petList = petService.list();
        // 即使列表为空,也返回成功(空列表也是合法数据)
        return R.success(petList);
    }

    /**
     * 根据ID修改宠物信息
     * @param pet 要修改的宠物信息(需包含ID)
     * @return 统一返回结果
     */
    @PutMapping("/update")
    public R<Boolean> updatePet(@RequestBody Pet pet) {
        // 参数校验:ID不能为空,名称/品种不能为空,年龄需大于0
        if (pet == null || pet.getId() == null || pet.getId() <= 0) {
            return R.error(ResultCode.PARAM_ERROR);
        }
        if (!StringUtils.hasText(pet.getName()) || !StringUtils.hasText(pet.getBreed())) {
            return R.error(ResultCode.PARAM_ERROR);
        }
        if (pet.getAge() != null && pet.getAge() <= 0) {
            return R.error(400, "宠物年龄必须大于0");
        }
        // 先校验数据是否存在
        if (!petService.existsById(pet.getId())) {
            return R.error(ResultCode.DATA_NOT_FOUND);
        }
        // 执行修改操作
        boolean updateFlag = petService.updateById(pet);
        if (updateFlag) {
            return R.success(true);
        } else {
            return R.error(ResultCode.ERROR);
        }
    }

    /**
     * 根据ID删除宠物信息
     * @param id 宠物ID
     * @return 统一返回结果
     */
    @DeleteMapping("/{id}")
    public R<Boolean> deletePet(@PathVariable Long id) {
        // 参数校验:ID不能为空且大于0
        if (id == null || id <= 0) {
            return R.error(ResultCode.PARAM_ERROR);
        }
        // 先校验数据是否存在
        if (!petService.existsById(id)) {
            return R.error(ResultCode.DATA_NOT_FOUND);
        }
        // 执行删除操作
        boolean deleteFlag = petService.removeById(id);
        if (deleteFlag) {
            return R.success(true);
        } else {
            return R.error(ResultCode.ERROR);
        }
    }
}

关于统一返回类的设计见Springboot3 | 统一返回类设计:从问题到实现

3.5 启动类

最后创建SpringBoot启动类,放在com.example.petmanage包下:

java 复制代码
package com.example.petmanage;

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

@SpringBootApplication
// 扫描Mapper接口(也可以在Mapper接口上加@Mapper注解,二选一即可)
@MapperScan("com.example.petmanage.mapper")
public class PetManageApplication {
    public static void main(String[] args) {
        SpringApplication.run(PetManageApplication.class, args);
    }
}

第四步:接口测试

启动项目后,我们可以用PostMan、Apifox等工具测试接口,这里给出核心测试用例:

4.1 新增宠物

json 复制代码
{
  "name": "旺财",
  "breed": "金毛",
  "age": 3
}
  • 响应:true(新增成功)

4.2 查询单个宠物

json 复制代码
{
  "id": 1,
  "name": "旺财",
  "breed": "金毛",
  "age": 3
}

4.3 查询所有宠物

json 复制代码
[
  {
    "id": 1,
    "name": "旺财",
    "breed": "金毛",
    "age": 3
  }
]

4.4 修改宠物信息

json 复制代码
{
  "id": 1,
  "name": "旺财",
  "breed": "金毛",
  "age": 4
}
  • 响应:true(修改成功)

4.5 删除宠物

核心逻辑总结

整个过程中,我们几乎没写一行SQL,核心就是复用了MyBatis-Plus的两个核心类:

  1. BaseMapper:封装了Mapper层的基础CRUD方法,无需手动编写XML或注解SQL;
  2. IService/ServiceImpl:进一步封装了Service层的业务逻辑,提供了更友好的调用方式。

这种方式的优势很明显:

  • 减少重复代码:不用为每个实体类写基础的增删改查SQL;
  • 降低出错概率:MyBatis-Plus的封装经过了大量验证,比手写SQL更稳定;
  • 提升开发效率:专注业务逻辑,而非基础的数据库操作。

如果需要扩展复杂查询(比如按品种查询宠物),也可以基于MyBatis-Plus的条件构造器QueryWrapper实现,后续有机会再聊。

总之,SpringBoot3+MyBatis-Plus的组合,能让我们以极低的成本搞定基础的数据库操作,把更多精力放在业务本身------这也是日常开发中"偷懒"的智慧。

相关推荐
沙白猿15 小时前
Redis报错:A bean with that name has already been defined in class path resource
spring boot·redis·mybatis
小马爱打代码17 小时前
MyBatis设计模式:构建者、工厂、代理模式
设计模式·mybatis·代理模式
柒.梧.1 天前
SSM常见核心面试问题深度解析
java·spring·面试·职场和发展·mybatis
rabbit_pro2 天前
Java使用Mybatis-Plus封装动态数据源工具类
java·python·mybatis
IT_Octopus2 天前
java 实体属性 Map 解决 mybatis-plus wrapper selectone 查mysql json类型为null 问题
java·mysql·mybatis
Dolphin_Home2 天前
MyBatis 核心属性详解笔记(由浅入深)
笔记·mybatis
一直都在5722 天前
MyBatis入门:CRUD、参数处理与防 SQL 注入
java·sql·mybatis
while(1){yan}2 天前
MyBatis Generator
数据库·spring boot·java-ee·mybatis