共计 18362 个字符,预计需要花费 46 分钟才能阅读完成。
欢送拜访我的 GitHub
https://github.com/zq2599/blog_demos
内容:所有原创文章分类汇总及配套源码,波及 Java、Docker、Kubernetes、DevOPS 等;
本文是《MyBatis 高级实战》系列的第二篇,通过前文咱们晓得了如何在 SpringBoot 中集成 MyBatis,本篇就一起来练习基本功:增删改查;
本篇概览
本篇要练习的内容如下:
- 单表的增删改查
- 批量新增
- 联表查问
全文由以下局部组成:
- 新建工程
- 减少启动类
- 减少 swagger 的配置类,工程蕴含了 swagger,以便稍后在浏览器上验证
- 减少配置文件
- 减少实体类
- 减少 mapper 配置文件
- 减少 mapper 接口
- 减少 service,调用 mapper 接口
- 减少 controller,调用 service 服务
- 编写单元测试用例
- 验证
源码下载
- 如果您不想编码,能够在 GitHub 下载所有源码,地址和链接信息如下表所示 (https://github.com/zq2599/blo…:
名称 | 链接 | 备注 |
---|---|---|
我的项目主页 | https://github.com/zq2599/blo… | 该我的项目在 GitHub 上的主页 |
git 仓库地址 (https) | https://github.com/zq2599/blo… | 该我的项目源码的仓库地址,https 协定 |
git 仓库地址 (ssh) | git@github.com:zq2599/blog_demos.git | 该我的项目源码的仓库地址,ssh 协定 |
- 这个 git 我的项目中有多个文件夹,本章的利用在 <font color=”blue”>mybatis</font> 文件夹下,如下图红框所示:
开发
- 本文的实战应用的数据库和表构造与前文《MyBatis 高级实战之一:Spring Boot 集成》截然不同;
- 前文《MyBatis 高级实战之一:Spring Boot 集成》新建了父工程 mybatis,本文持续在此工程中新增子工程,名为 <font color=”blue”>curd</font>,整个子工程文件构造如下:
- 批改父工程 mybatis 的 <font color=”blue”>pom.xml</font>,在 <font color=”blue”>dependencyManagement</font> 节点下新增两个 dependency 节点,如下所示,这么做是为了对立治理依赖库的版本:
<!-- swagger-ui --> | |
<dependency> | |
<groupId>io.springfox</groupId> | |
<artifactId>springfox-swagger-ui</artifactId> | |
<version>2.5.0</version> | |
</dependency> | |
<dependency> | |
<groupId>com.google.code.gson</groupId> | |
<artifactId>gson</artifactId> | |
<version>2.8.6</version> | |
</dependency> |
- 名为 <font color=”blue”>curd</font> 子工程,其 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>com.bolingcavalry</groupId> | |
<artifactId>mybatis</artifactId> | |
<version>1.0-SNAPSHOT</version> | |
<relativePath>../pom.xml</relativePath> | |
</parent> | |
<groupId>com.bolingcavalry</groupId> | |
<artifactId>curd</artifactId> | |
<version>0.0.1-SNAPSHOT</version> | |
<name>curd</name> | |
<description>Demo project for Mybatis CURD in Spring Boot</description> | |
<properties> | |
<java.version>1.8</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> | |
</dependency> | |
<dependency> | |
<groupId>mysql</groupId> | |
<artifactId>mysql-connector-java</artifactId> | |
<scope>runtime</scope> | |
</dependency> | |
<dependency> | |
<groupId>org.springframework.boot</groupId> | |
<artifactId>spring-boot-starter-test</artifactId> | |
<scope>test</scope> | |
<exclusions> | |
<exclusion> | |
<groupId>org.junit.vintage</groupId> | |
<artifactId>junit-vintage-engine</artifactId> | |
</exclusion> | |
</exclusions> | |
</dependency> | |
<dependency> | |
<groupId>io.springfox</groupId> | |
<artifactId>springfox-swagger2</artifactId> | |
</dependency> | |
<!-- swagger-ui --> | |
<dependency> | |
<groupId>io.springfox</groupId> | |
<artifactId>springfox-swagger-ui</artifactId> | |
</dependency> | |
<dependency> | |
<groupId>junit</groupId> | |
<artifactId>junit</artifactId> | |
<scope>test</scope> | |
</dependency> | |
<dependency> | |
<groupId>com.google.code.gson</groupId> | |
<artifactId>gson</artifactId> | |
</dependency> | |
</dependencies> | |
<build> | |
<plugins> | |
<plugin> | |
<groupId>org.springframework.boot</groupId> | |
<artifactId>spring-boot-maven-plugin</artifactId> | |
</plugin> | |
</plugins> | |
</build> | |
</project> |
- 减少启动类,留神要用 MapperScan 正文来指定 mapper 接口代码的包门路:
package com.bolingcavalry.curd; | |
import org.mybatis.spring.annotation.MapperScan; | |
import org.springframework.boot.SpringApplication; | |
import org.springframework.boot.autoconfigure.SpringBootApplication; | |
@SpringBootApplication | |
@MapperScan("com.bolingcavalry.curd.mapper") | |
public class CurdApplication {public static void main(String[] args) {SpringApplication.run(CurdApplication.class, args); | |
} | |
} |
- 本次实战用到了 swagger,这样能够很不便的通过浏览器向各个 controller 接口发送申请,以下是配置类:
package com.bolingcavalry.curd; | |
import springfox.documentation.service.Contact; | |
import org.springframework.context.annotation.Bean; | |
import org.springframework.context.annotation.Configuration; | |
import springfox.documentation.builders.ApiInfoBuilder; | |
import springfox.documentation.builders.PathSelectors; | |
import springfox.documentation.builders.RequestHandlerSelectors; | |
import springfox.documentation.service.ApiInfo; | |
import springfox.documentation.service.Tag; | |
import springfox.documentation.spi.DocumentationType; | |
import springfox.documentation.spring.web.plugins.Docket; | |
import springfox.documentation.swagger2.annotations.EnableSwagger2; | |
@Configuration | |
@EnableSwagger2 | |
public class SwaggerConfig { | |
@Bean | |
public Docket createRestApi() {return new Docket(DocumentationType.SWAGGER_2) | |
.apiInfo(apiInfo()) | |
.tags(new Tag("UserController", "用户服务"), new Tag("LogController", "日志服务")) | |
.select() | |
// 以后包门路 | |
.apis(RequestHandlerSelectors.basePackage("com.bolingcavalry.curd.controller")) | |
.paths(PathSelectors.any()) | |
.build();} | |
// 构建 api 文档的详细信息函数, 留神这里的注解援用的是哪个 | |
private ApiInfo apiInfo() {return new ApiInfoBuilder() | |
// 页面题目 | |
.title("MyBatis CURD 操作") | |
// 创建人 | |
.contact(new Contact("程序员欣宸", "https://github.com/zq2599/blog_demos", "zq2599@gmail.com")) | |
// 版本号 | |
.version("1.0") | |
// 形容 | |
.description("API 形容") | |
.build();} | |
} |
- application.yml 内容如下:
server: | |
port: 8080 | |
spring: | |
# 数据源 | |
datasource: | |
username: root | |
password: 123456 | |
url: jdbc:mysql://192.168.50.43:3306/mybatis?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC | |
driver-class-name: com.mysql.cj.jdbc.Driver | |
# mybatis 配置 | |
mybatis: | |
# 配置文件所在位置 | |
config-location: classpath:mybatis-config.xml | |
# 映射文件所在位置 | |
mapper-locations: classpath:mappers/*Mapper.xml | |
# 日志配置 | |
logging: | |
level: | |
root: INFO | |
com: | |
bolingcavalry: | |
curd: | |
mapper: debug |
- 减少 user 表的实体类 User.java,外面带有 swagger 的注解,不便在 swagger 页面展现:
package com.bolingcavalry.curd.entity; | |
import io.swagger.annotations.ApiModel; | |
import io.swagger.annotations.ApiModelProperty; | |
@ApiModel(description = "用户实体类") | |
public class User {@ApiModelProperty(value = "用户 ID") | |
private Integer id; | |
@ApiModelProperty(value = "用户名", required = true) | |
private String name; | |
@ApiModelProperty(value = "用户地址", required = false) | |
private Integer age; | |
@Override | |
public String toString() { | |
return "User{" + | |
"id=" + id + | |
", name='" + name + '\'' + | |
", age=" + age + | |
'}'; | |
} | |
// 省去 get 和 set 办法,请您自行补齐 | |
} |
- 减少 log 表的实体类 Log.java,外面带有 swagger 的注解,不便在 swagger 页面展现:
package com.bolingcavalry.curd.entity; | |
import io.swagger.annotations.ApiModel; | |
import io.swagger.annotations.ApiModelProperty; | |
import java.sql.Date; | |
/** | |
* @Description: 实体类 | |
* @author: willzhao E-mail: zq2599@gmail.com | |
* @date: 2020/8/4 8:24 | |
*/ | |
@ApiModel(description = "日志实体类") | |
public class Log {@ApiModelProperty(value = "日志 ID") | |
private Integer id; | |
@ApiModelProperty(value = "用户 ID") | |
private Integer userId; | |
@ApiModelProperty(value = "日志内容") | |
private String action; | |
@ApiModelProperty(value = "创立工夫") | |
private Date createTime; | |
@Override | |
public String toString() { | |
return "Log{" + | |
"id=" + id + | |
", userId=" + userId + | |
", action='" + action + '\'' + | |
", createTime=" + createTime + | |
'}'; | |
} | |
// 省去 get 和 set 办法,请您自行补齐 | |
} |
- 为联表查问的后果筹备一个 bean,名为 LogExtend.java,继承自 Log.java,本人只有个 userName 字段,对应联表查问 user 表的 name 字段:
package com.bolingcavalry.curd.entity; | |
import io.swagger.annotations.ApiModel; | |
import io.swagger.annotations.ApiModelProperty; | |
@ApiModel(description = "日志实体类 ( 含用户表的字段)") | |
public class LogExtend extends Log {public String getUserName() {return userName;} | |
public void setUserName(String userName) {this.userName = userName;} | |
@ApiModelProperty(value = "用户名") | |
private String userName; | |
@Override | |
public String toString() { | |
return "LogExtend{" + | |
"id=" + getId() + | |
", userId=" + getUserId() + | |
", userName='" + getUserName() + '\'' + | |
", action='" + getAction() + '\'' + | |
", createTime=" + getCreateTime() + | |
'}'; | |
} | |
} |
- 减少 user 表的 mapper 映射文件,可见都是些很简略 sql,要留神的是批量新增的节点,这外面用到了 <font color=”blue”>foreach</font> 语法,能够通过汇合动静生成 sql:
<?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.bolingcavalry.curd.mapper.UserMapper"> | |
<select id="sel" parameterType="int" resultType="user"> | |
select * from user where id = #{id} | |
</select> | |
<!-- 新增单条记录 --> | |
<insert id="insertWithFields" useGeneratedKeys="true" keyProperty="id"> | |
insert into user (id, name, age) values (#{id}, #{name}, #{age}) | |
</insert> | |
<!-- 批量新增 --> | |
<insert id="insertBatch" useGeneratedKeys="true" keyProperty="id"> | |
insert into user (id, name, age) | |
values | |
<foreach collection="users" item="user" separator=","> | |
(#{user.id}, #{user.name}, #{user.age}) | |
</foreach> | |
</insert> | |
<!-- 依照名称查找 --> | |
<select id="findByName" parameterType="String" resultType="user"> | |
select id, name, age from user where name like concat('%', #{name}, '%') | |
</select> | |
<!-- 删除指定数据 --> | |
<delete id="delete"> | |
delete from user where id= #{id} | |
</delete> | |
<!-- 删除所有数据 --> | |
<delete id="clearAll"> | |
delete from user | |
</delete> | |
<!-- 更新 --> | |
<update id="update"> | |
update user set name = #{name}, age = #{age} where id = #{id} | |
</update> | |
<!-- 获取总数 --> | |
<select id="totalCount" resultType="java.lang.Integer"> | |
select count(*) from user | |
</select> | |
</mapper> |
- 减少 log 表的 mapper 映射文件,如下所示,请关注联表操作 <font color=”blue”>selExtend</font>,其后果是 logExtendResultMap:
<?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.bolingcavalry.curd.mapper.LogMapper"> | |
<resultMap id="logExtendResultMap" type="logExtend"> | |
<id property="id" column="id"/> | |
<result column="user_id" jdbcType="INTEGER" property="userId"/> | |
<result column="action" jdbcType="VARCHAR" property="action"/> | |
<result column="create_time" jdbcType="TIMESTAMP" property="createTime"/> | |
<result column="user_name" jdbcType="TIMESTAMP" property="userName"/> | |
</resultMap> | |
<!-- 新增单条记录 --> | |
<insert id="insertWithFields" useGeneratedKeys="true" keyProperty="id" parameterType="log"> | |
insert into log (id, user_id, action, create_time) values (#{id}, #{userId}, #{action}, #{createTime}) | |
</insert> | |
<select id="selExtend" parameterType="int" resultMap="logExtendResultMap"> | |
select l.id as id, | |
l.user_id as user_id, | |
l.action as action, | |
l.create_time as create_time, | |
u.name as user_name | |
from log as l | |
left join user as u | |
on l.user_id = u.id | |
where l.id = #{id} | |
</select> | |
</mapper> |
- 减少用户表的 mapper 接口类 <font color=”blue”>UserMapper.java</font>,对应着映射文件中的 sql 节点的 id:
package com.bolingcavalry.curd.mapper; | |
import com.bolingcavalry.curd.entity.LogExtend; | |
import com.bolingcavalry.curd.entity.User; | |
import org.springframework.stereotype.Repository; | |
import java.util.List; | |
@Repository | |
public interface UserMapper {User sel(int id); | |
int insertWithFields(User user); | |
int insertBatch(List<User> users); | |
int clearAll(); | |
List<User> findByName(String name); | |
int update(User user); | |
int delete(int id); | |
int totalCount(); | |
LogExtend selExtend(int id); | |
} |
- 减少日志表的 mapper 接口类 <font color=”blue”>LogMapper.java</font>,对应着映射文件中的 sql 节点的 id:
package com.bolingcavalry.curd.mapper; | |
import com.bolingcavalry.curd.entity.Log; | |
import com.bolingcavalry.curd.entity.LogExtend; | |
import org.springframework.stereotype.Repository; | |
@Repository | |
public interface LogMapper {Log sel(int id); | |
LogExtend selExtend(int id); | |
int insertWithFields(Log log); | |
} |
- mapper 接口实现后就是 service 层,先写 user 表的 service,如下所示,可见都是对 mapper 接口的调用:
package com.bolingcavalry.curd.service; | |
import com.bolingcavalry.curd.entity.User; | |
import com.bolingcavalry.curd.mapper.UserMapper; | |
import org.springframework.beans.factory.annotation.Autowired; | |
import org.springframework.stereotype.Service; | |
import java.util.List; | |
@Service | |
public class UserService { | |
@Autowired | |
UserMapper userMapper; | |
public User sel(int id) {return userMapper.sel(id); | |
} | |
public User insertWithFields(User user) {userMapper.insertWithFields(user); | |
return user; | |
} | |
public List<User> insertBatch(List<User> users) {userMapper.insertBatch(users); | |
return users; | |
} | |
public int clearAll() {return userMapper.clearAll(); | |
} | |
public List<User> findByName(String name) {return userMapper.findByName(name); | |
} | |
public int update(User user) {return userMapper.update(user); | |
} | |
public int delete(int id) {return userMapper.delete(id); | |
} | |
public int totalCount() {return userMapper.totalCount(); | |
} | |
} |
- 还有 log 表的 service:
package com.bolingcavalry.curd.service; | |
import com.bolingcavalry.curd.entity.Log; | |
import com.bolingcavalry.curd.entity.LogExtend; | |
import com.bolingcavalry.curd.entity.User; | |
import com.bolingcavalry.curd.mapper.LogMapper; | |
import org.springframework.beans.factory.annotation.Autowired; | |
import org.springframework.stereotype.Service; | |
@Service | |
public class LogService { | |
@Autowired | |
LogMapper logMapper; | |
public Log sel(int id){return logMapper.sel(id); | |
} | |
public LogExtend selExtend(int id) {return logMapper.selExtend(id); | |
} | |
public Log insertWithFields(Log log) {logMapper.insertWithFields(log); | |
return log; | |
} | |
} |
- 最初是 controller 层了,因为应用了 swagger,导致 controller 绝对上一篇稍微简单(多了些注解):
package com.bolingcavalry.curd.controller; | |
import com.bolingcavalry.curd.entity.User; | |
import com.bolingcavalry.curd.service.UserService; | |
import io.swagger.annotations.Api; | |
import io.swagger.annotations.ApiImplicitParam; | |
import io.swagger.annotations.ApiOperation; | |
import org.springframework.beans.factory.annotation.Autowired; | |
import org.springframework.web.bind.annotation.*; | |
import java.util.ArrayList; | |
import java.util.List; | |
@RestController | |
@RequestMapping("/user") | |
@Api(tags = {"UserController"}) | |
public class UserController { | |
@Autowired | |
private UserService userService; | |
@ApiOperation(value = "新增 user 记录", notes="新增 user 记录") | |
@RequestMapping(value = "/insertwithfields",method = RequestMethod.PUT) | |
public User create(@RequestBody User user) {return userService.insertWithFields(user); | |
} | |
@ApiOperation(value = "批量新增 user 记录", notes="批量新增 user 记录") | |
@RequestMapping(value = "/insertbatch", method = RequestMethod.PUT) | |
public List<User> insertBatch(@RequestBody List<User> users) {return userService.insertBatch(users); | |
} | |
@ApiOperation(value = "删除指定 ID 的 user 记录", notes="删除指定 ID 的 user 记录") | |
@ApiImplicitParam(name = "id", value = "用户 ID", paramType = "path", required = true, dataType = "Integer") | |
@RequestMapping(value = "/{id}", method = RequestMethod.DELETE) | |
public int delete(@PathVariable int id){return userService.delete(id); | |
} | |
@ApiOperation(value = "删除 user 表所有数据", notes="删除 user 表所有数据") | |
@RequestMapping(value = "/clearall", method = RequestMethod.DELETE) | |
public int clearAll(){return userService.clearAll(); | |
} | |
@ApiOperation(value = "依据 ID 批改 user 记录", notes="依据 ID 批改 user 记录") | |
@RequestMapping(value = "/update", method = RequestMethod.POST) | |
public int update(@RequestBody User user){return userService.update(user); | |
} | |
@ApiOperation(value = "依据名称含糊查找所有 user 记录", notes="依据名称含糊查找所有 user 记录") | |
@ApiImplicitParam(name = "name", value = "用户名", paramType = "path", required = true, dataType = "String") | |
@RequestMapping(value = "/findbyname/{name}", method = RequestMethod.GET) | |
public List<User> findByName(@PathVariable("name") String name){return userService.findByName(name); | |
} | |
@ApiOperation(value = "依据 ID 查找 user 记录", notes="依据 ID 查找 user 记录") | |
@ApiImplicitParam(name = "id", value = "用户 ID", paramType = "path", required = true, dataType = "Integer") | |
@RequestMapping(value = "/{id}", method = RequestMethod.GET) | |
public User GetUser(@PathVariable int id){return userService.sel(id); | |
} | |
@ApiOperation(value = "获取总数", notes="获取总数") | |
@RequestMapping(value = "/totalcount", method = RequestMethod.GET) | |
public int totalcount(){return userService.totalCount(); | |
} | |
} |
- log 的 controller 如下:
package com.bolingcavalry.curd.controller; | |
import com.bolingcavalry.curd.entity.Log; | |
import com.bolingcavalry.curd.entity.LogExtend; | |
import com.bolingcavalry.curd.service.LogService; | |
import io.swagger.annotations.Api; | |
import io.swagger.annotations.ApiImplicitParam; | |
import io.swagger.annotations.ApiOperation; | |
import org.springframework.beans.factory.annotation.Autowired; | |
import org.springframework.web.bind.annotation.*; | |
@RestController | |
@RequestMapping("/log") | |
@Api(tags = {"LogController"}) | |
public class LogController { | |
@Autowired | |
private LogService logService; | |
@ApiOperation(value = "依据 ID 查找日志记录", notes="依据 ID 查找日志记录") | |
@ApiImplicitParam(name = "id", value = "日志 ID", paramType = "path", required = true, dataType = "Integer") | |
@RequestMapping(value = "/{id}", method = RequestMethod.GET) | |
public LogExtend logExtend(@PathVariable int id){return logService.selExtend(id); | |
} | |
@ApiOperation(value = "新增日志记录", notes="新增日志记录") | |
@RequestMapping(value = "/insertwithfields",method = RequestMethod.PUT) | |
public Log create(@RequestBody Log log) {return logService.insertWithFields(log); | |
} | |
} |
- 最初是一段单元测试的代码,咱们试试通过 junit 进行自测,如下所示,可见一共测试了三个 controller 接口:先新增,再查找,最初删除,要留神的是 MockMvc 的用法,以及 jsonPath 办法的用法,还有就是通过 Order 注解管制执行程序(肯定要增加 TestMethodOrder 注解,否则 Order 注解不失效):
package com.bolingcavalry.curd.controller; | |
import com.bolingcavalry.curd.entity.User; | |
import com.google.gson.Gson; | |
import com.google.gson.JsonArray; | |
import com.google.gson.JsonParser; | |
import org.junit.Ignore; | |
import org.junit.jupiter.api.*; | |
import org.junit.runner.RunWith; | |
import org.springframework.beans.factory.annotation.Autowired; | |
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; | |
import org.springframework.boot.test.context.SpringBootTest; | |
import org.springframework.http.MediaType; | |
import org.springframework.test.context.junit4.SpringRunner; | |
import org.springframework.test.web.servlet.MockMvc; | |
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; | |
import java.util.List; | |
import java.util.UUID; | |
import static org.hamcrest.Matchers.hasSize; | |
import static org.hamcrest.Matchers.is; | |
import static org.hamcrest.core.IsEqual.equalTo; | |
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; | |
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; | |
@RunWith(SpringRunner.class) | |
@SpringBootTest | |
@AutoConfigureMockMvc | |
@TestMethodOrder(MethodOrderer.OrderAnnotation.class) | |
class UserControllerTest { | |
@Autowired | |
private MockMvc mvc; | |
// user 表的 name 字段,这里为了保障测试时新增和删除的记录是同一条,用 UUID 作为用户名 | |
static String testName; | |
@BeforeAll | |
static void init() {testName = UUID.randomUUID().toString().replaceAll("-","");; | |
} | |
@Test | |
@Order(1) | |
void insertWithFields() throws Exception {String jsonStr = "{\"name\": \"" + testName + "\", \"age\": 10}"; | |
mvc.perform(MockMvcRequestBuilders.put("/user/insertwithfields") | |
.contentType(MediaType.APPLICATION_JSON) | |
.content(jsonStr) | |
.accept(MediaType.APPLICATION_JSON)) | |
.andExpect(status().isOk()) | |
.andExpect(jsonPath("$.name", is(testName))) | |
.andDo(print()) | |
.andReturn() | |
.getResponse() | |
.getContentAsString();} | |
@Test | |
@Order(2) | |
void findByName() throws Exception {mvc.perform(MockMvcRequestBuilders.get("/user/findbyname/"+ testName).accept(MediaType.APPLICATION_JSON)) | |
.andExpect(status().isOk()) | |
.andExpect(jsonPath("$", hasSize(1))) | |
.andDo(print()); | |
} | |
@Test | |
@Order(3) | |
void delete() throws Exception { | |
// 先依据名称查出记录 | |
String responseString = mvc.perform(MockMvcRequestBuilders.get("/user/findbyname/"+ testName).accept(MediaType.APPLICATION_JSON)) | |
.andExpect(status().isOk()) | |
.andExpect(jsonPath("$", hasSize(1))) | |
.andDo(print()) | |
.andReturn() | |
.getResponse() | |
.getContentAsString(); | |
// 反序列化失去数组 | |
JsonArray jsonArray = JsonParser.parseString(responseString).getAsJsonArray(); | |
// 反序列化失去 user 实例 | |
User user = new Gson().fromJson(jsonArray.get(0), User.class); | |
// 执行删除 | |
mvc.perform(MockMvcRequestBuilders.delete("/user/"+ user.getId()).accept(MediaType.APPLICATION_JSON)) | |
.andExpect(status().isOk()) | |
.andExpect(content().string(equalTo("1"))) | |
.andDo(print()); | |
} | |
} |
- 至此编码完结,开始验证上述性能;
单元测试验证
- IDEA 关上 <font color=”blue”>UserControllerTest.java</font>,点击下图红框中的图标即可开始执行单元测试:
- 单元测试实现后 IDEA 会给出后果,如下图,红框右侧能够查看具体的测试过程数据:
- 篇幅所限,这只有大量的单元测试用例,接下来用 swagger 来验证每个接口;
swagger 验证 web 接口
- 如下图,启动 CurdApplication 类:
- 浏览器拜访:http://localhost:8080/swagger-ui.html,即可关上 swagger 页面,如下图:
- 先试试新增的接口,操作如下图:
- 点击了上图红框 3 的 Try it out! 按钮后,响应信息如下图,可见操作胜利:
- 限于篇幅,其余接口的测试就不逐个列出了,请您自行验证;
- 至此,MyBatis 的根本增删改查和简略的联表操作的实战就实现了,接下来咱们会持续摸索 MyBatis 的基本操作;
你不孤独,欣宸原创一路相伴
- Java 系列
- Spring 系列
- Docker 系列
- kubernetes 系列
- 数据库 + 中间件系列
- DevOps 系列
欢送关注公众号:程序员欣宸
微信搜寻「程序员欣宸」,我是欣宸,期待与您一起畅游 Java 世界 …
https://github.com/zq2599/blog_demos
正文完