序言:
微服务是一种软件架构风格,它是以专注于单一职责的很多小型项目为基础,组合出复杂的大型应用。
想学习SpringCloud搭建项目,首先我们需要学习的就是Mybatis和Docker。
大家在日常开发中应该能发现,单表的CRUD功能代码重复度很高,也没有什么难度。而这部分代码量往往比较大,开发起来比较费时。
因此,目前企业中都会使用一些组件来简化或省略单表的CRUD开发工作。目前在国内使用较多的一个组件就是MybatisPlus.
本专栏系列皆是基于黑马程序员的课程《java黑马商城项目微服务实战开发》进行编写,笔者一步步跟随课程进行项目开发,也会把自身遇到的问题错误全都记录下来,从初学者的角度出发,希望能在一些细微之处帮助到各位读者,大家通过本博客辅助课程视频能够达到更好的学习效果。
本文用到的代码及相关PPT大家也可以自行去课程链接进行下载使用。
课程链接:java黑马商城项目微服务实战开发
Mybatis-Plus
首先我们先把数据库配置好,本博客参考的是黑马程序员的SpringCloud微服务商城项目。
Part1.基础环境搭建
1.首先我们会拿到一个mp-demo的文件,把这个文件导入idea。
2.我们会有一个mp.sql的数据库文件,我自己用的是Navicat,把mp.sql导入数据库。
3.建立idea和mp数据库的联系。
Part2.尝试使用Mybatis进行代码优化入门案例
1.在pom.xml里引入依赖
<!--MybatisPlus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3.1</version>
</dependency>
2.给UserMapper找个爸爸
3.我们可以运行一下test测试类里的方法,会发现是可以正常运行的,是绿的。
由于我个人用的是JDK21 这个课程的lombok和JDK的版本比较老,就会出现ERROR:java: java.lang.NoSuchFieldError: Class com.sun.tools.javac.tree.JCTree$JCImport does not have m
解决办法也很简单,可以用老版本的JDK,但是我更为推荐第二种
我们可以在依赖库中更新lombok的版本
这个是JDK21更新后的Bug,我们只要把lombok更正为1.18.30以上版本就可以解决这个异常。
4.删这些手写的方法
5.在测试类里更改
根据类型进行一一修改,我们run一下会发现完全ok,不需要那么多冗杂的简单代码。
Part3.Mybatis-Plus常用注解与配置
一.常用注解
类名驼峰转下划线作为表名
名为id的字段作为主键
变量名驼峰转下划线作为表的字段名
如:createTime→create_time
通过这种方式mp就可以自动识别,帮我们完成简单的sql语句。
但如果我们没有按照规范的写法,mp就需要我们自己去定义了。
@TableName:用来指定表名
@TableId:用来指定表中的主键字段信息
@TableFieId:用来指定表中的普通字段信息
如图,虽然咱们是规范写法,就是做一个示意。
尤其要注意
①isMarried这种带is作为判断的boolean类型的值,我们的mp在识别时候会因为把带is的识别为布尔型去掉is,这样就会出现歧义,我们一定要给这种变量加一个@TableFieId注解。
②还有一些像叫order的,和数据库关键字有冲突,我们就需要@TableFieId(“`order”)来解决冲突。
③还有一些数据库中不存在的数据,可能分库分表处理后,但是这个类里有,我们需要设置@TableFieId(exist=false)来进行处理。
二.常用配置
基本上是都不用咱们配置,可能有一些特殊需求咱们再做细微的改动,具体的功能作用都可以去查官方文档。
如图简单改改,我们把老的mybatis删掉,功能测试也都是一样可以run的。
Part4.Mybatis-Plus核心功能
一.条件构造器
案例1基于QueryWrapper的查询
需求1:查询出名字中带o的,存款大于等于1000元的人的id、username、binfo、balance字段
需求2:更新用户名为jack的用户的余额为2000
需求3:更新id为1,2,4的用户的余额,扣200。
需求4:用Lambda实现需求1
我们在实际编程中,尽量使用LambdaQueryWrapper和LambdaUpdateWrapper,避免硬编码这种情况。
二.自定义SQL
需求:将id在指定范围内的用户(例如1,2,4)的余额扣减指定值。
1.先编写一个测试
2.根据给定的查询条件(wrapper)更新用户余额。
具体功能如下:
使用@Param("ew")标注的QueryWrapper<User>类型参数wrapper来指定需要更新余额的用户条件。
使用@Param("amount")标注的int类型参数amount来表示需要更新的金额数。
函数执行更新操作,但未明确说明具体的更新逻辑(如是增加还是减少)。
3.拼接
这样我们就可以用mp定义where语句(复杂的查询需要几十行,用mp就很简单),简单的部分再手搓
三.Service接口
我们可以看到IService也提供了特别多,功能也都涵盖了增删改查,通过Service接口我们可以非常便捷的操作一堆以前需要写for-each循环的代码。
我们通常需要先定义一个UserService接口,再用一个UserServiceImpl去开发业务,在开发业务中,我们需要现在UserService里定义方法,再去UserServiceImpl实现方法。
现在我们通过IService,我们直接先让接口继承他,我们的Service就提供了很多方法,那以前写的UserServiceImpl就需要重写很多方法,那不是更麻烦吗,诶,mp给我们提供了ServiceImpl都帮咱们重写好了,我们一样实现类也继承mp的实现类。
逻辑理通了,现在我们来上手实际操作一下。
1.先按照老传统定义接口和实现类。
2.然后分别继承IService和IServiceImpl
3.现在我们来写一个新增测试类看看实际效果,注意包的结构,是新建的ServiceTest包!!!
我们run一下看看结果
我们再来搞一个查询试试效果哈
诶,一样完美查询,mp真牛逼吧孩子。
四.案例·基于Restful风格实现下面的接口:
1.首先我们先引进来两个依赖
<!--swagger-->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi2-spring-boot-starter</artifactId>
<version>4.1.0</version>
</dependency>
<!--web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
2.然后再配置一下swagger
这个配置大家不用去改哈,那个controller我们一会会给他创建出来
knife4j:
enable: true
openapi:
title: 用户管理接口文档
description: "用户管理接口文档"
email: zhanghuyi@itcast.cn
concat: 虎哥
url: https://www.itcast.cn
version: v1.0.0
group:
default:
group-name: default
api-rule: package
api-rule-resources:
- com.itheima.mp.controller
3.导入dto、vo
4.创建一个controller文件夹,定义UserController类。
然后我发现这个地方红一半,Controller不红,Mapping红了。
然后我发现是一个愚蠢的错误,我把RequestMappin写成了RestMapping,怪不得红,简单修改一下就绿了。
5.我们现在依托于接口参数编写接口
我们现在来写第一个新增用户的接口,关于代码注释,我写的很详细,大家看图哪怕没有很深的基础也可以看懂。
遇到的问题:
完整的controller代码如下
package com.itheima.mp.controller;
import cn.hutool.core.bean.BeanUtil;
import com.itheima.mp.domain.dto.UserFormDTO;
import com.itheima.mp.domain.po.User;
import com.itheima.mp.domain.vo.UserVO;
import com.itheima.mp.service.IUserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import java.util.List;
//定义了一个RESTful API控制器,用于处理与用户相关的HTTP请求
@Api(tags = "用户管理接口")
//标注@RestController和@RequestMapping("/users"),
//表示这是一个处理HTTP请求的控制器,所有请求路径以/users开头。
@RestController
@RequestMapping ("/users")
@RequiredArgsConstructor
public class UserController {
private final IUserService userService;
//相比于AutoWire Mybatis-Plus提倡我们用构造函数来注入依赖,我们可以用lombok来简化代码编写
@PostMapping
//saveUser方法标注@PostMapping,处理POST请求,位于/users路径下
@ApiOperation("新增用户接口")
//方法接收JSON格式的UserFormDTO对象,将其转换为User对象
//并调用userService.save(user)保存用户信息。
public void saveUser(@RequestBody UserFormDTO userDTO){
//我们有mp之后,拿到手先想mp有没有封装好的方法,有就直接用,没有就自己手写
//1.把DTO拷贝到PO
User user=BeanUtil.copyProperties(userDTO,User.class);
//2.新增
userService.save(user);
}
@DeleteMapping
@ApiOperation("删除用户接口")
public void deleteUserById(@ApiParam("用户id") @PathVariable("id") Long id){
userService.removeById(id);
}
@GetMapping("{id}")
@ApiOperation("根据id查询用户接口")
public UserVO queryUserById(@ApiParam("用户id")@PathVariable("id") Long id){
//1.查询用户PO
User user = userService.getById(id);
//2.把PO拷贝到VO
return BeanUtil.copyProperties(user, UserVO.class);
}
@GetMapping
@ApiOperation("根据id查询用户接口")
public List<UserVO> queryUserByIds(@ApiParam("用户id集合")@RequestParam("ids") List<Long> ids){
//1.查询用户PO
List<User> users = userService.listByIds(ids);
//2.把PO拷贝到VO
return BeanUtil.copyToList(users, UserVO.class);
}
}
第五个接口带业务逻辑,我们就需要自己定义service和mapper了
1.先和以前一样在controller写逻辑
然后deductBanlance这个方法不是mp的自带方法,它会报红,现在我们去实现这个方法
2.在service里先进行声明
3.在serviceImpl里进行方法的实现
4.在mapper实现
现在我们来尝试以下我们编写的service是否能够正常运行
1.用alt+8启动service→启动SpringBoot
2.打开本地网页
http://localhost:8080//doc.html#/home
3.测试代码
新增功能好使
查询功能也好使
然后就是最复杂的扣除余额功能,我们发现也是oo又kk,响应码200说明我们的代码运行成功。
感谢阅读。