前言
增删改查是后端最基本的技能。下面我就带领小伙伴们通过一个简单的示例来讲解SpringBoot的增删改查。Spring Boot框架层次从上至下可分为5层:分别为View层,Controller层,Service层,Mapper层,Model层
1. View层:视图根据接受到的数据最终展示页面给用户浏览,需要与Controller层结合起来使用
2. Controller层:负责具体的业务模块流程的控制,响应用户的请求,调用Service层的接口来控制业务流程,决定使用何种视图并准备响应数据,并把接收到的参数传给Mapper,调用Mapper的方法接口
3. Service层:主要负责业务模块的逻辑应用设计,同时有一些是关于数据库处理的操作,但是不是直接和底层数据库相关联,而是首先设计接口,再设计实现其中的类,在接口实现方法中需要导入Mapper层,接着在Spring的配置文件中配置其实现的关联,从而在应用中调用Service接口来进行业务处理
4. Mapper层:主要是做数据持久层的工作,同时提供增删改查工作,Mapper层也是首先设计接口,再设计实现其中的类,具体实现在mapper.xml文件中,然后就可以在模块中调用此接口来进行数据业务的处理
5. Model层:创建对象,包括构造器和get、set方法和toString方法
Controller层:沟通前后端,注解为@RestController
Service层:沟通Mapper层和Controller层,注解为@Service
Mapper层:沟通数据库和Service层,注解为@Repository
我们以一个简单的用户管理来讲解SpringBoot增删改查的实例
1. 创建数据库
首先创建数据库mydb,然后创建数据表,数据表创建语句如下:
create table if not exists user(
id int unsigned not null auto_increment comment "用户ID",
nickname varchar(32) not null comment "昵称",
avater varchar(250) not null comment "头像",
phone varchar(11) not null comment "手机号",
create_time datetime not null comment "创建时间",
update_time datetime not null comment "更新时间",
state tinyint(1) default 1 comment "用户状态 1:正常;0:禁用;默认:1"
primary key(id)
)ENGINE=innodb DEFAULT CHARSET=utf8
insert into user values(1,"老舅妈撸代码","https://profile-avatar.csdnimg.cn/b4a1fe618b454834b630acdebf8a29a9_qq_41765777.jpg","17861857725","2023-09-22 15:53:12",null,1);
insert into user values(2,"快乐的老田","https://profile-avatar.csdnimg.cn/fe6a31a2c2a340f492494ebe9c15f638_lvrouhuosha1o.jpg","15069987814","2023-09-22 16:02:12",null,1);
2. 创建项目,安装所需依赖(包括Swagger)
pom.xml配置文件代码
<?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.17-SNAPSHOT</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<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>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter-test</artifactId>
<version>2.3.1</version>
<scope>test</scope>
</dependency>
<!-- Swagger-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<!-- Swagger-UI -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<releases>
<enabled>false</enabled>
</releases>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
<pluginRepository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<releases>
<enabled>false</enabled>
</releases>
</pluginRepository>
</pluginRepositories>
</project>
3. 配置数据库连接,配置SpringBoot
配置/main/resources/application.properties文件
#端口号配置
server.port=9099
#数据源相关配置
spring.datasource.url=jdbc:mysql://localhost:3306/finshing?serverTimezone=UTC&&characterEncoding=UTF-8&allowMultiQueries=true
spring.datasource.password=123456
spring.datasource.username=root
#mybatis映射对应的实体类位置
mybatis.type-aliases-package=com.example.demo.entity
#mybatis的映射xml文件路径位置
mybatis.mapper-locations=classpath:/mapper/*Mapper.xml
#开启数据库下划线映射Java驼峰
mybatis.configuration.map-underscore-to-camel-case: true
spring.mvc.view.prefix=/pages/
spring.mvc.view.suffix=.html
spring.mvc.pathmatch.matching-strategy = ant_path_matcher
# 配置上传文件大小限制
# 单个文件大小配置
spring.servlet.multipart.maxFileSize=30MB
# 请求总大小配置
spring.http.multipart.maxRequestSize = 30MB
4. 配置Swagger接口文档
添加src/main/java/com/example/demo/configclass/SwaggerConfig.java文件,配置Swagger,配置成功后访问:localhost:9099/swagger-ui.html即可访问swagger接口说明文档
package com.example.demo.configclass;
import com.google.common.reflect.Parameter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.ParameterBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2) // DocumentationType.SWAGGER_2 固定的,代表swagger2
// .groupName("分布式任务系统") // 如果配置多个文档的时候,那么需要配置groupName来分组标识
.apiInfo(apiInfo()) // 用于生成API信息
.select() // select()函数返回一个ApiSelectorBuilder实例,用来控制接口被swagger做成文档
.apis(RequestHandlerSelectors.basePackage("com.example.demo.controller")) // 用于指定扫描哪个包下的接口
.paths(PathSelectors.any())// 选择所有的API,如果你想只为部分API生成文档,可以配置这里
.build().globalOperationParameters(Arrays.asList(
new ParameterBuilder()
.name("Token")
.description("Token验证")
.modelRef(new ModelRef("string"))
.parameterType("header")
.required(false)
.build()
// ,
// new ParameterBuilder()
// .name("X-Custom-Header")
// .description("Custom header")
// .modelRef(new ModelRef("string"))
// .parameterType("header")
// .required(false)
// .build()
)
);
}
/**
* 用于定义API主界面的信息,比如可以声明所有的API的总标题、描述、版本
* @return
*/
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("XX项目API") // 可以用来自定义API的主标题
.description("XX项目SwaggerAPI管理") // 可以用来描述整体的API
.termsOfServiceUrl("") // 用于定义服务的域名
.version("1.0") // 可以用来定义版本。
.build()
; //
}
}
5. 封装返回结果工具类
src/main/java/com/example/demo/utils/ResultUtil.java,在utils目录下创建ResultUtil.java工具类,用于对返回结果的封装。
{
code: 200,
msg:"操作成功",
data:[ ], // 或者{ }、number、nul、string、boolean
}
package com.example.demo.utils;
import lombok.Data;
/**
* @author yeqc
* @date 2022/3/28 21:54
*/
@Data
public class ResultUtil<T> {
public static final Integer SUCCESS_CODE = 200;
public static final Integer FAIL_CODE = 4000;
public static final String SUCCESS_MESSAGE = "操作成功";
public static final String FAIL_MESSAGE = "操作失败";
/**
* 返回状态码
*/
private Integer code;
/**
* 返回信息
*/
private String message;
/**
* 返回数据
*/
private T data;
private int count;
private ResultUtil() {
}
public static <T> ResultUtil<T> success() {
ResultUtil<T> resultUtil = new ResultUtil<>();
resultUtil.setCode(SUCCESS_CODE);
resultUtil.setMessage(SUCCESS_MESSAGE);
return resultUtil;
}
public static <T> ResultUtil<T> success(T data) {
ResultUtil<T> resultUtil = success();
resultUtil.setData(data);
return resultUtil;
}
public static <T> ResultUtil<T> success(String message, T data) {
ResultUtil<T> resultUtil = success();
resultUtil.setMessage(message);
resultUtil.setData(data);
return resultUtil;
}
public static <T> ResultUtil<T> success(Integer code, String message, T data) {
ResultUtil<T> resultUtil = new ResultUtil<>();
resultUtil.setCode(code);
resultUtil.setMessage(message);
resultUtil.setData(data);
return resultUtil;
}
public static <T> ResultUtil<T> success(Integer code, String message,Integer count, T data) {
ResultUtil<T> resultUtil = new ResultUtil<>();
resultUtil.setCode(code);
resultUtil.setMessage(message);
resultUtil.setCount(count);
resultUtil.setData(data);
return resultUtil;
}
public static <T> ResultUtil<T> fail() {
ResultUtil<T> resultUtil = new ResultUtil<>();
resultUtil.setCode(FAIL_CODE);
resultUtil.setMessage(FAIL_MESSAGE);
return resultUtil;
}
public static <T> ResultUtil<T> fail(T data) {
ResultUtil<T> resultUtil = fail();
resultUtil.setData(data);
return resultUtil;
}
public static <T> ResultUtil<T> fail(String message, T data) {
ResultUtil<T> resultUtil = fail();
resultUtil.setMessage(message);
resultUtil.setData(data);
return resultUtil;
}
public static <T> ResultUtil<T> fail(Integer code, String message) {
ResultUtil<T> resultUtil = fail();
resultUtil.setCode(code);
resultUtil.setMessage(message);
return resultUtil;
}
public static <T> ResultUtil<T> fail(Integer code, String message, T data) {
ResultUtil<T> resultUtil = new ResultUtil<>();
resultUtil.setCode(code);
resultUtil.setMessage(message);
resultUtil.setData(data);
return resultUtil;
}
public void setCode(int code){
this.code = code;
}
public int getCode(){
return this.code;
}
public void setMessage(String message){
this.message = message;
}
public String getMessage(){
return message;
}
public void setData(T data){
this.data = data;
}
public T getData(){
return data;
}
public void setCount(int count){
this.count = count;
}
public int getCount(){
return count;
}
}
6. 创建Controller控制器
package com.example.demo.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import com.example.demo.entity.User;
import com.example.demo.service.serviceImpl.UserServiceImpl;
import java.util.List;
import com.example.demo.utils.ResultUtil;
@Api(tags = "人员相关操作")
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
UserServiceImpl userServiceImpl;
// 获取用户列表
@ApiOperation(value = "获取用户列表")
@GetMapping("/list")
public ResultUtil<List<User>> list(){
return ResultUtil.success(userServiceImpl.list());
}
// 获取用户信息
@ApiOperation(value = "获取用户信息")
@GetMapping("/info")
public ResultUtil<User> info(@RequestParam int id){
return ResultUtil.success(userServiceImpl.info(id));
}
// 添加用户
@ApiOperation(value = "添加用户")
@PostMapping("/add")
public ResultUtil<String> add(@RequestBody User user){
if(userServiceImpl.add(user) == 1){
return ResultUtil.success("操作成功");
}else{
return ResultUtil.fail("操作失败");
}
}
// 编辑用户
@ApiOperation(value = "编辑用户")
@PostMapping("/update")
public ResultUtil<String> update(@RequestBody User user){
if(userServiceImpl.update(user) == 1){
return ResultUtil.success("操作成功");
}else{
return ResultUtil.fail("操作失败");
}
}
// 删除用户
@ApiOperation(value = "删除用户")
@PostMapping("/delete")
public ResultUtil<String> delete(@RequestBody int[] ids){
userServiceImpl.delete(ids);
return ResultUtil.success("操作成功");
}
// 关注用户
@ApiOperation(value = "关注用户")
@PostMapping("/forward")
public String forward(){
return "/user/forward";
}
}
7. 创建Service层
创建service接口类,src/main/java/com/example/demo/service/UserService.java
package com.example.demo.service;
import com.example.demo.entity.User;
import java.util.List;
public interface UserService {
// 列表
List<User> list();
// 信息
User info(int id);
// 新增用户
int add(User user);
// 更新
int update(User user);
// 删除
void delete(int[] ids);
}
创建service接口实现类,src/main/java/com/example/demo/service/serviceImpl/UserServiceImpl.java
package com.example.demo.service.serviceImpl;
import com.example.demo.entity.User;
import com.example.demo.service.UserService;
import com.example.demo.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
@Component
public class UserServiceImpl implements UserService{
@Autowired
UserMapper userMapper;
@Override
public List<User> list(){
return userMapper.list();
}
@Override
public User info(int id){
return userMapper.info(id);
}
@Override
public int add(User user){
return userMapper.add(user);
}
@Override
public int update(User user){
return userMapper.update(user);
}
@Override
public void delete(int[] ids){
userMapper.delete(ids);
}
}
8. 创建Mapper
创建Mapper接口类,src/main/java/com/example/demo/mapper/UserMapper.java
package com.example.demo.mapper;
import com.example.demo.entity.User;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Component;
import java.util.List;
@Mapper
@Component
public interface UserMapper {
// 列表
List<User> list();
// 信息
User info(int id);
// 添加
int add(User user);
// 更新
int update(User user);
// 删除
void delete(int[] ids);
}
创建MapperXML文件类,src/main/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.demo.mapper.UserMapper">
<!-- 获取单个人信息 -->
<select id="info" parameterType="Integer" resultType="User">
select * from user where id = #{id}
</select>
<!-- 获取列表信息 -->
<select id="list" resultType="User">
select * from user
</select>
<!-- 删除 -->
<delete id="delete">
delete from user where id in
<foreach collection="array" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
<!-- 添加 -->
<insert id="add" useGeneratedKeys="true" keyProperty="id">
insert into user(id,nickname,phone,avater,create_time,update_time,state)
values(
#{id},#{nickname},#{phone},#{avater},#{createTime,jdbcType=TIMESTAMP},#{updateTime,jdbcType=TIMESTAMP},#{state}
)
</insert>
<!-- 更新 -->
<update id="update" useGeneratedKeys="true" keyProperty="id">
update user
<set>
nickname = #{nickname},
phone = #{phone},
avater = #{avater},
create_time = #{createTime},
update_time = #{updateTime},
state = #{state},
</set>
where id = #{id}
</update>
</mapper>