从0开始实现一个简单的增删改查

题目

1
2
3
4
5
6
7
8
9
10
11
12
13
14
create table  t_requirement  
(
i_require_id BIGINT primary key auto_increment not null comment '需求标识',
s_title VARCHAR(256) comment '需求标题',
s_description VARCHAR(2048) comment '需求描述',
s_comment VARCHAR(1024) comment '备注',
i_source TINYINT comment '需求来源 枚举,1内部、2外部',
s_require_aim_meaning VARCHAR(512) comment '业务目的及意义',
s_require_background_current VARCHAR(512) comment '需求背景及现状',
d_post_date DATETIME comment '提出时间',
d_wish_date DATETIME comment '期望完成时间'
) comment '需求管理表';
alter table t_requirement add constraint PK_t_requient_i_requi_id426B primary key (i_require_id);


1
2
3
4
5
6
7
8
9
使用以上SQL语句,基于MySQL或其他数据库创建一个【需求管理表】。并基于该表实现基本的 新增 和 查询 业务接口,具体要求如下:
1、数据库连接方式不限,可通过JDBC或其他业务框架实现。
2、新增:做好接口请求参数的基本校验,包括:需求标题、需求来源为必填项,需求标题、需求描述分别不能超过2050个字符。
3、查询:支持通过需求标题进行模糊查询。

验证:
1、 接口必填参数未赋值时,请求返回错误状态码400,成功则返回状态码200
2、 新增的数据可通过查询接口进行筛选。
3、 通过浏览器http请求或postman等工具进行验证。

思路分析

  • 整体框架使用String Boot 加 MyBatis Plus实现
  • 这里需要对字符串进行长度校验,可以通过Hibernate Validator来实现,spring-boot-starter-web集成了这个工具
  • 定义Result类,用来统一返回结果
  • 使用全局异常处理类来处理异常
  • 定义枚举类来实现source字段

创建项目,引入依赖,运行SQL,编写配置

由于idea版本过高,这里创建项目时只能使用JDK 17及以上版本,创建好项目后我会在pom文件中改为JDK 8

image-20240413132306576 image-20240413132557212

还需要而外引入的依赖有:MyBatis Plus、Lombok

1
2
3
4
5
6
7
8
9
10
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>

运行SQL语句,创建对应的SQL表


创建application.yaml,写入相关配置

1
2
3
4
5
6
7
8
9
10
11
12
13
server:
port: 8080
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/text?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
username: root
password: "020427"
mybatis-plus:
mapper-locations: classpath:mapping/*.xml
type-aliases-package: com.zheng.entity



创建枚举类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Getter
public enum Source {
INTERIOR(1,"内部"),
EXTERNAL(2,"外部");

@EnumValue
private int code;
private String value;
Source(Integer code, String value) {
this.code = code;
this.value = value;
}
}

  • @EnumValue:哪个属性被标注,数据库就会保存哪个属性,由于数据库source的是tinyint类型的,这里标记code

创建实体类

hibernate validator提供了很多注解,让我们在创建实体类时,能够对其中的属性进行约束

注解 说明
@NotNull 被注释的元素(任何元素)必须不为null,但集合为空也是可以的。没啥实际意义
@NotEmpty 用来校验字符串、集合、map、数组不能为null或空 (字符串传入空格也不可以)(集合需至少包含一个元素)功能强于@NotNull
@NotBlank 只用来校验字符串不为null,不为空值,不为全空格。功能强大于@NotEmpty
@Size(max=, min=) 指定的字符串、集合、map、数组长度必须在指定的max和min范围内。(允许元素为null,字符串允许为空格)
@Length(min=,max=) 只用来校验字符串,长度必须在指定的max和min范围内。(允许元素为null)
@Range(min=,max=) 用来校验数字或字符串的大小必须在指定的min和max范围内,字符串会转成数字进行比较,如果不是数字校验不通过。(允许元素为null)
@Min() 校验数字(包括integer、short、long、int等)的最小值,不支持小数即double和float。(允许元素为null)
@Max() 校验数字(包括integer、short、long、int等)的最大值,不支持小数即double和float。(允许元素为null)
@Pattern() 正则表达式匹配,可用来校验年月日格式是否包含特殊字符
@Valid 递归的对关联对象进行校验,如果关联对象是个集合或者数组,那么对其中的元素进行递归校验,如果是一个map,则对其中的值部分进行校验

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
package com.zheng.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.Date;

@TableName("t_requirement")
@NoArgsConstructor
@AllArgsConstructor
@Data
public class Requirement {
@TableField("i_require_id")
private Integer requireId;

@TableField("s_title")
@NotBlank(message = "标题不能为空")
@Length(min = 1, max = 20, message = "需求标题不能超过20个字符")
private String title;

@Length(max = 50, message = "需求描述不能超过50个字符")
@TableField("s_description")
private String description;

@TableField("s_comment")
private String comment;

@NotNull(message = "需求源不能为空")
@TableField("i_source")
private Source source;

@TableField("s_require_aim_meaning")
private String requireAmiMeaning;

@TableField("s_require_background_current")
private String requireBackgroundCurrent;

@TableField("d_post_date")
private Date postDate;

@TableField("d_wish_date")
private Date wishDate;

}

创建统一返回结果类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package com.zheng.util;

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

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result {
private Integer code;
private String msg;
private Object data;

/**
* @description: 成功响应,不带数据
*/
public static Result Success() {
return new Result(200, "success", null);
}

/**
* @description: 成功响应,带数据
*/
public static Result Success(Object data) {
return new Result(200, "success", data);
}

/**
* @description: 错误响应
*/
public static Result Error(String msg) {
return new Result(400, msg, null);
}
}

创建全局异常处理类

用来处理,必填字段非空,或者字段超出长度限制

1
2
3
4
5
6
7
8
9
10
11
12
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<Result> handleValidationExceptions(MethodArgumentNotValidException ex) {
// 获取验证失败的错误信息
String errorMessage = ex.getBindingResult().getFieldError().getDefaultMessage();
// 创建一个Result对象
Result result = Result.Error(errorMessage);
// 返回状态码400和Result对象
return new ResponseEntity<>(result, HttpStatus.BAD_REQUEST);
}
}

controller层

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@RestController
@RequestMapping("/requirement")
public class RequirementController {
private final RequirementService requirementService;

@Autowired
public RequirementController(RequirementService requirementService) {
this.requirementService = requirementService;
}

/**
* @description: 创建新需求信息
*/
@PostMapping
private Result create(@Valid @RequestBody Requirement requirement) {
return requirementService.create(requirement);
}

/**
* @description: 查询需求信息,可以根据title模糊查询
*/
@GetMapping()
private Result get(@RequestParam(required = false) String title) {
return requirementService.get(title);
}

}

service层

1
2
3
4
5
public interface RequirementService extends IService<Requirement> {
Result create(Requirement requirement);

Result get(String title);
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Service
public class RequirementServiceImpl extends ServiceImpl<RequirementMapper, Requirement> implements RequirementService {

@Autowired
private RequirementMapper requirementMapper;

@Override
public Result create(Requirement requirement) {
requirementMapper.insert(requirement);
return Result.Success();
}

@Override
public Result get(String title) {
QueryWrapper<Requirement> wrapper = new QueryWrapper<>();
if (title != null) {
wrapper.like("s_title", title);
}
List<Requirement> requirements = requirementMapper.selectList(wrapper);
return Result.Success(requirements);
}
}

mapper层

1
2
3
@Mapper
public interface RequirementMapper extends BaseMapper<Requirement> {
}

POM文件

编写代码的过程中可能又引入了一些依赖,这里给出所有依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.6</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.zheng</groupId>
<artifactId>Interview</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>Interview</name>
<description>Interview</description>
<properties>
<java.version>8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.2.0.Final</version>
</dependency>

</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

</project>

整体项目架构图

image-20240414002819319

新增测试

没有输入标题,提示标题不能为空,符合要求


没有输入需求来源,提示需求源不能为空,符合要求


标题长度超过20个字符,输出需求标题不能超过20个字符,符合要求


需求描述超过50个字符,提示需求描述不能超过50个字符


输入符合要求的数据,返回200,保存成功

image-20240414002022914


模糊查询测试

现在数据库中的数据


测试不输入title,也就是查询所有,总共6条数据,符合要求

image-20240414002354547


根据Title模糊查询,添加Title,值为测试,共查询到两条数据,符合要求

image-20240414002528719


从0开始实现一个简单的增删改查
https://lzhengjy.github.io/2024/04/13/从0开始实现一个简单的增删改查/
作者
Zheng
发布于
2024年4月13日
许可协议