写点什么

MyBatis 初级实战之二:增删改查

作者:Java高工P7
  • 2021 年 11 月 11 日
  • 本文字数:7188 字

    阅读完需:约 24 分钟

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


  1. 增加 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 方法,请您自行补齐


}


  1. 增加 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 方法,请您自行补齐


}


  1. 为联表查询的结果准备一个 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() +


'}';


}


}


  1. 增加 user 表的 mapper 映射文件,可见都是些很简单 sql,要注意的是批量新增的节点,这里面用到了 foreach 语法,可以通过集合动态生成 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 col


【一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义】
浏览器打开:qq.cn.hn/FTf 免费领取
复制代码


lection="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>


  1. 增加 log 表的 mapper 映射文件,如下所示,请关注联表操作 selExtend,其结果是 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>


  1. 增加用户表的 mapper 接口类 UserMapper.java ,对应着映射文件中的 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);


}


  1. 增加日志表的 mapper 接口类 LogMapper.java,对应着映射文件中的 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);


}


  1. 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();


}


}


  1. 还有 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;


}


}


  1. 最后是 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();


}


}


  1. 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);


}


}


  1. 最后是一段单元测试的代码,咱们试试通过 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());


}


}


  • 至此编码结束,开始验证上述功能;

单元测试验证

  1. IDEA 打开 UserControllerTest.java,点击下图红框中的图标即可开始执行单元测试:



  1. 单元测试完成后 IDEA 会给出结果,如下图,红框右侧可以查看详细的测试过程数据:

用户头像

Java高工P7

关注

还未添加个人签名 2021.11.08 加入

还未添加个人简介

评论

发布
暂无评论
MyBatis初级实战之二:增删改查