给新人看的Mybatis-Plus入门

351 阅读8分钟

给新人看的Mybatis-Plus入门

编辑历史:

2023-07-27 13:27,15:32

涉及到如下知识点:Mybatis-Plus Service CRUD接口,Mybatis-Plus分页插件,RESTful API,MapStuct

新手上路,作为自己的学习记录分享出来

2023-10-10 16:53,修改示例,修改数据库为 H2 数据库,不再使用 Mysql 数据库

宜提桶跑路 goodgoodwork,daydayup

参考资料:

baomidou: baomidou.com/pages/226c2…

springdoc: springdoc.org/

0、前置条件

IDEA:我的版本IntelliJ IDEA 2021.2.1 (Ultimate Edition) 
Java Version: Jdk 8+
H2 DataBase

1、使用Gradle构建一个新的Spring Boot Project

使用IDEA新建一个项目或在已有的Project中新建一个模块

如图所示,我的项目名称:lkcoffee,项目SDK选择了 Java 8 , Spring Boot 版本 2.7.14, 选择了 Spring Web\ lombok \ H2 依赖

2023-07-27-1.png

Snipaste_2023-07-27_14-36-34.png

Spring Boot 3.0 + 版本需要 Jdk 17+ 的样子

如图所示,是生成的项目结构

Snipaste_2023-07-27_13-47-34.png

settings.gradle 是项目的根目录,目前 settings.gradle 的内容如下,定义了根项目的名称:

rootProject.name = 'lkcoffee'

build.gradle 是项目的构建文件,目前 build.gradle 的内容如下,定义了使用了哪些插件,java的版本,依赖项,测试使用JUnit5等信息:

plugins {
    id 'java'
    id 'org.springframework.boot' version '2.7.14'
    id 'io.spring.dependency-management' version '1.0.15.RELEASE'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'

java {
    sourceCompatibility = '1.8'
}

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    runtimeOnly 'com.h2database:h2'
    compileOnly 'org.projectlombok:lombok'
    annotationProcessor 'org.projectlombok:lombok'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

tasks.named('test') {
    useJUnitPlatform()
}

LkcoffeeApplication 是我们的启动类,目前 LkcoffeeApplication 的内容如下:

package com.example.lkcoffee;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class LkcoffeeApplication {

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

}

application.properties 是项目的配置文件,目前 application.properties 的内容为空,后面我添加一些配置。另一种配置文件的格式是 application.yml格式,我更喜欢使用这种格式配置属性。

通过在 application.yml 配置文件中添加一些配置,如,定义项目的名称,修改项目的默认端口号8080

spring:
  application:
    name: lkcoffee
server:
  port: 8888

2023-07-27 13:54,总而言之,一个 production-gradeself-containedSpring Boot应用已经创建了,现在就可以直接运行了。

试试看,点击LkcoffeeApplication 启动类左旁的绿色小三角,如下是我的控制台输出内容:

  .   ____          _            __ _ _
 /\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )___ | '_ | '_| | '_ / _` | \ \ \ \
 \/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |___, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::               (v2.7.14)

2023-07-27 13:55:46.102  INFO 75552 --- [           main] c.example.lkcoffee.LkcoffeeApplication   : No active profile set, falling back to 1 default profile: "default"
2023-07-27 13:55:47.622  INFO 75552 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8888 (http)
2023-07-27 13:55:47.675  INFO 75552 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2023-07-27 13:55:47.675  INFO 75552 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.78]
2023-07-27 13:55:47.829  INFO 75552 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2023-07-27 13:55:47.829  INFO 75552 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1705 ms
2023-07-27 13:55:48.303  INFO 75552 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8888 (http) with context path ''
2023-07-27 13:55:48.313  INFO 75552 --- [           main] c.example.lkcoffee.LkcoffeeApplication   : Started LkcoffeeApplication in 2.552 seconds (JVM running for 3.118)

应用程序正在运行,访问:http://localhost:8888/ 你会看到如下报错信息,接下类让我们继续完善这个项目。

Whitelabel Error Page

This application has no explicit mapping for /error, so you are seeing this as a fallback.
Thu Jul 27 14:05:32 CST 2023
There was an unexpected error (type=Not Found, status=404).

2、使用 MyBatis-Plus 来实现单表的增删改查

初始化数据库表

新建一个名为 lkcoffee 的 数据库,假设有一张 coffee 表,coffee表中有如下字段,主键ID,咖啡名称、品牌、售价、评分

生成数据库表对应的数据库脚本如下:schema-h2.sql

DROP TABLE IF EXISTS coffee;

CREATE TABLE coffee
(
    id           INT PRIMARY KEY AUTO_INCREMENT,
    name         VARCHAR(100)  NOT NULL,
    brand        VARCHAR(50)   NOT NULL,
    price        DECIMAL(6, 2) NOT NULL,
    introduction VARCHAR(500),
    rating       DECIMAL(3, 1) NOT NULL DEFAULT 0
);

插入数据对应的数据库脚本如下:data-h2.sql

DELETE FROM coffee;

INSERT INTO coffee (name, brand, price, introduction, rating)
VALUES
    ('拿铁', '瑞幸咖啡', 26.50, '瑞幸经典拿铁', 4.2),
    ('美式咖啡', '星巴克', 22.00, '星巴克咖啡经典美式', 4.5),
    ('摩卡', '瑞幸咖啡', 28.00, '瑞幸摩卡咖啡', 4.3),
    ('馥芮白', '星巴克', 32.50, '星巴克馥芮白咖啡', 4.8),
    ('焦糖玛奇朵', '瑞幸咖啡', 30.00, '瑞幸焦糖玛奇朵咖啡', 4.6),
    ('卡布奇诺', '星巴克', 25.00, '星巴克经典卡布奇诺', 4.4),
    ('雀巢特浓咖啡', '雀巢咖啡', 18.50, '雀巢特浓咖啡,独特口感', 4.1),
    ('香草拿铁', '瑞幸咖啡', 27.00, '瑞幸香草拿铁咖啡', 4.7),
    ('冰美式咖啡', '星巴克', 24.00, '星巴克冰镇美式咖啡', 4.3),
    ('瑞纳冰', '瑞幸咖啡', 29.50, '瑞幸经典瑞纳冰咖啡', 4.5);

添加依赖

对于Maven项目,在 pom.xml 文件中添加如下依赖(2023-07-27 14:09,mybatis-plus 最新版本3.5.3.1)

<!-- https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-boot-starter -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.3.1</version>
</dependency>

对于Gradle项目,在build.gradle文件中 dependencies{} 中 添加如下依赖

// https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-boot-starter
implementation group: 'com.baomidou', name: 'mybatis-plus-boot-starter', version: '3.5.3.1'

配置数据库连接

application.yml 配置文件中添加 H2 数据库(数据库名称lkcoffee)的相关配置

spring:
  application:
    name: lkcoffee
  datasource:
    url: jdbc:h2:mem:lkcoffee
    driverClassName: org.h2.Driver
    username: root
    password: toor
    generate-unique-name: false
    name: mooncake
  jpa:
    show-sql: true
    hibernate:
      ddl-auto: update
      use-new-id-generator-mappings: false
  h2:
    console:
      path: /h2-console
      enabled: true
      settings:
        trace: false
        web-allow-others: false
  #  security:
  #    user:
  #      name: admin
  #      password: password
  sql:
    init:
      schema-locations: classpath:/schema-h2.sql
      data-locations: classpath:/data-h2.sql
server:
  port: 8888

开始编码

如下图,是使用Mybatis-Plus代码生成器生成的代码(按照我的框架),后面还有精力的话我会补充。

Snipaste_2023-07-27_14-43-31.png

Coffee 实体类

首先是 com.example.lkcoffee.persistence.entity 包下的 Coffee 实体类

package com.example.lkcoffee.persistence.entity;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

import java.math.BigDecimal;

/**
 * @version 1.0
 * @since 2023/10/10 17:22
 */
@Data
@TableName(value = "coffee")
public class Coffee {


    @TableId(value = "ID", type = IdType.AUTO)
    private Integer id;

    @TableField(value = "name")
    private String name;

    @TableField(value = "brand")
    private String brand;

    @TableField(value = "price")
    private BigDecimal price;

    @TableField(value = "introduction")
    private String introduction;

    @TableField(value = "rating")
    private BigDecimal rating;

}

CoffeeMapper Mapper 接口

com.example.lkcoffee.persistence.mapper 包下的

package com.example.lkcoffee.persistence.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.lkcoffee.persistence.entity.Userinfo;

/**
 * <p>
 *  Mapper 接口
 * </p>
 *
 * @author lkcoffee
 * @since 2023-07-27 02:31:10
 */
@Mapper
public interface CoffeeMapper extends BaseMapper<Coffee> {

}

CoffeeMapper.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.lkcoffee.persistence.mapper">
    
</mapper>

CoffeeServiceImpl 服务实现类

package com.example.lkcoffee.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.lkcoffee.persistence.entity.Userinfo;
import com.example.lkcoffee.persistence.mapper.UserinfoMapper;
import com.example.lkcoffee.service.IUserinfoService;
import org.springframework.stereotype.Service;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author lkcoffee
 * @since 2023-07-27 02:31:10
 */
@Service
public class CoffeeServiceImpl extends ServiceImpl<CoffeeMapper, Coffee> implements CoffeeService {
}

CoffeeService 服务类接口

package com.example.lkcoffee.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.example.lkcoffee.persistence.entity.Userinfo;

/**
 * <p>
 *  服务类
 * </p>
 *
 * @author lkcoffee
 * @since 2023-07-27 02:31:10
 */
public interface CoffeeService extends IService<Coffee> {
    
}

配置MapperScan

Spring Boot 启动类中添加 @MapperScan 注解,扫描 Mapper 文件夹:

package com.example.lkcoffee;

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

@SpringBootApplication
@MapperScan("com.example.lkcoffee.persistence.mapper")
public class LkcoffeeApplication {

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

}

测试应用程序运行

2023-07-27 14:53,现在,在应用程序中运行代码,看到控制台有如下输出,程序没有报错,一切似乎运行正常

 _ _   |_  _ _|_. ___ _ |    _ 
| | |/|_)(_| | |_\  |_)||_|_\ 
     /               |         
                        3.5.3.1 

3、编写REST ful API 接口

这一步,我们在控制器中添加方法以支持响应前端对后端的HTTP请求。

初始化 CoffeeController

在之前的框架中,com.example.lkcoffee.controller 包下CoffeeController类,目前的内容如下

package com.example.lkcoffee.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author lkcoffee
 * @since 2023-07-27 02:31:10
 */
@RestController
@RequestMapping("/coffee")
public class CoffeeController {
    
}

补充CoffeeController

我们在控制器中注入对应的 IUserinfoService ,并根据需要编写相应的接口方法,使用 MyBatis-Plus 进行数据的 CRUD 操作

package com.example.lkcoffee.controller;

import com.example.lkcoffee.persistence.entity.Userinfo;
import com.example.lkcoffee.service.IUserinfoService;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author lkcoffee
 * @since 2023-07-27 02:31:10
 */
@RestController
@RequestMapping("/coffee")
public class CoffeeController {


    private final CoffeeService coffeeService;

    @Autowired
    public CoffeeController(CoffeeService coffeeService) {
        this.coffeeService = coffeeService;
    }

    @GetMapping("/list")
    public ResponseEntity<List<Coffee>> getCoffeeList() {
        List<Coffee> coffeeList = coffeeService.list();
        return ResponseEntity.ok(coffeeList);
    }

    @GetMapping("/{id}")
    public ResponseEntity<Coffee> getCoffeeById(@PathVariable Integer id) {
        Coffee coffee = coffeeService.getById(id);
        return ResponseEntity.ok(coffee);
    }

    @PostMapping("/save")
    public ResponseEntity<Void> saveCoffee(@RequestBody Coffee coffee) {
        coffeeService.save(coffee);
        return ResponseEntity.status(HttpStatus.CREATED).build();
    }

    @PutMapping("/update")
    public ResponseEntity<Void> updateCoffeeById(@RequestBody Coffee coffee) {
        coffeeService.updateById(coffee);
        return ResponseEntity.noContent().build();
    }

    @DeleteMapping("/{id}")
    public ResponseEntity<Void> deleteCoffeeById(@PathVariable Integer id) {
        coffeeService.removeById(id);
        return ResponseEntity.noContent().build();
    }
}

在上述代码中,我们通过 @Resource 注解将 CoffeeService 自动注入到控制器中。然后,我们定义了四个接口方法来实现对用户信息的增删改查操作。

  • saveCoffee 方法使用 @PostMapping 注解来处理 POST 请求,并从请求体中获取 Coffee 对象,然后使用 coffeeService.save() 方法保存用户信息。

  • getCoffeeById 方法使用 @GetMapping 注解来处理 GET 请求,并从路径中获取 ID,然后使用 coffeeService.getById() 方法查询用户信息。

  • updateCoffeeById 方法使用 @PutMapping 注解来处理 PUT 请求,并从路径中获取 ID,同时从请求体中获取 Coffee 对象,然后设置 ID 并使用 coffeeService.updateById() 方法更新用户信息。

  • deleteCoffeeById 方法使用 @DeleteMapping 注解来处理 DELETE 请求,并从路径中获取 ID,然后使用 coffeeService.removeById() 方法删除用户信息。

验证接口

在浏览器中使用如下命令:http://localhost:8888/coffee/1 或者使用如下 curl -X GET http://localhost:8888/coffee/1 CURL 命令。这将向控制器发送一个GET请求,路径为/coffee/1,将返回id为1的coffee信息。

$ curl -X GET http://localhost:8888/coffee/1
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   110    0   110    0     0  37326      0 --:--:-- --:--:-- --:--:-- 55000{"id":1,"name":"拿铁","brand":"瑞幸咖啡","price":26.50,"introduction":"瑞幸经典拿铁","rating":4.2}

4、添加 Swagger-UI

后端不能没有Swagger-UI界面去调试后端接口,于是这一部分介绍如何在项目中添加

添加依赖

// https://mvnrepository.com/artifact/org.springdoc/springdoc-openapi-ui
implementation group: 'org.springdoc', name: 'springdoc-openapi-ui', version: '1.7.0'

在配置文件添加配置

springdoc:
  api-docs:
    enabled: true
    path: /v3/api-docs
  swagger-ui:
    path: /swagger-ui/index.html
    tagsSorter: alpha
    use-root-path: true
  cache:
    disabled: true

修改启动类

package com.example.lkcoffee;

import org.mybatis.spring.annotation.MapperScan;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.core.env.Environment;

import java.net.InetAddress;
import java.net.UnknownHostException;

@SpringBootApplication
@MapperScan("com.example.lkcoffee.persistence.mapper")
public class LkcoffeeApplication {

    private static final Logger logger = LoggerFactory.getLogger(LkcoffeeApplication.class);

    /**
     * Swagger地址:http://localhost:8080/swagger-ui/index.html#/
     * 参考资料:https://dzone.com/articles/openapi-3-documentation-with-spring-boot
     * @param args args
     */
    public static void main(String[] args) throws UnknownHostException {

        ApplicationContext applicationContext =  SpringApplication.run(LkcoffeeApplication.class, args);
        Environment environment = applicationContext.getEnvironment();

        logger.info("\n---------------------------------------------lkcoffee-----------------------------------------------------------------------\n" +
                        "应用 '{}' 运行成功! \n" +
                        "Swagger-UI-Interface 访问连接: http://{}:{}{}{} \n" +
                        "API-Docs 访问连接: http://{}:{}{}{} \n" +
                        "--------------------------------------------------------------------------------------------------------------------",

                environment.getProperty("spring.application.name"),

                InetAddress.getLocalHost().getHostAddress(),
                environment.getProperty("server.port", "8080"),
                environment.getProperty("server.servlet.context-path", ""),
                environment.getProperty("springdoc.swagger-ui.path", "/swagger-ui/index.html"),

                InetAddress.getLocalHost().getHostAddress(),
                environment.getProperty("server.port", "8080"),
                environment.getProperty("server.servlet.context-path", ""),
                environment.getProperty("springdoc.api-docs.path", "/v3/api-docs")

        );
    }
}

现在,可以重新启动应用运行应用根据控制台中输出的URL访问Swagger-UI界面查看效果了

5、添砖加瓦

以上仅仅是一些皮毛,在此基础上还有无限可能待补充,如使用Mybatis-Plus生成器生成代码框架,如使用分页插件进行分页查询,如使用ThreadPoolTaskExecutor 进行多线程开发。任重道远,但现在写不下去了~