【01】手把手教你0基础部署SpringCloud微服务商城教学-Mybatis篇(上)

news2024/10/10 16:38:38

序言:

微服务是一种软件架构风格,它是以专注于单一职责的很多小型项目为基础,组合出复杂的大型应用。

想学习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说明我们的代码运行成功。

感谢阅读。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2202511.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

IEC104规约的秘密之九----链路层和应用层

104规约从TCP往上&#xff0c;分成链路层和应用层。 如图&#xff0c;APCI就是链路层&#xff0c;ASDU的就是应用层 我们看到报文都是68打头的&#xff0c;因为应用层报文也要交给链路层发送&#xff0c;链路层增加了开头的6个字节再进行发送。 完全用于链路层的报文每帧都只有…

基于卷积神经网络的脊柱骨折识别系统,resnet50,mobilenet模型【pytorch框架+python】

更多目标检测和图像分类识别项目可看我主页其他文章 功能演示&#xff1a; 基于卷积神经网络的脊柱骨折识别系统&#xff0c;resnet50&#xff0c;mobilenet【pytorch框架&#xff0c;python&#xff0c;tkinter】_哔哩哔哩_bilibili &#xff08;一&#xff09;简介 基于卷…

C++ | Leetcode C++题解之第467题环绕字符串中唯一的子字符串

题目&#xff1a; 题解&#xff1a; class Solution { public:int findSubstringInWraproundString(string p) {vector<int> dp(26);int k 0;for (int i 0; i < p.length(); i) {if (i && (p[i] - p[i - 1] 26) % 26 1) { // 字符之差为 1 或 -25k;} els…

京东统一存储实践

​作者&#xff1a;王腾蛟&#xff0c;2021年8月加入京东&#xff0c;目前主要负责京东离线存储(HDFS)相关工作。 导读 随着大数据时代的到来&#xff0c;海量数据的存储与处理成为了众多企业面临的重要挑战。HDFS 作为一个高可靠性、高扩展性的分布式文件系统&#xff0c;在…

1招!统一管理多个微信,工作效率真的太高了!

你是否经常在使用多个微信号时感到疲惫不堪&#xff1f;每当你需要切换账号时&#xff0c;是不是得不停地登陆、登出&#xff0c;甚至要带着几台手机外出&#xff1f;这种繁琐的操作不仅浪费时间&#xff0c;还严重影响了工作效率。 今天&#xff0c;我将为你分享一款强大的多…

【优选算法】(第三十二篇)

目录 ⼆进制求和&#xff08;easy&#xff09; 题目解析 讲解算法原理 编写代码 字符串相乘&#xff08;medium&#xff09; 题目解析 讲解算法原理 编写代码 ⼆进制求和&#xff08;easy&#xff09; 题目解析 1.题目链接&#xff1a;. - 力扣&#xff08;LeetCode&a…

C语言-常见文件操作函数详解(fgetc,fputc,fgets,fputs,fscanf,fprintf,fread,fwrite)

&#x1f30f;个人博客&#xff1a;尹蓝锐的博客 希望文章能够给到初学的你一些启发&#xff5e; 如果觉得文章对你有帮助的话&#xff0c;点赞 关注 收藏支持一下笔者吧&#xff5e; 顺序读写数据常用函数 函数名调用形式功能返回值fgetcfgetc(fp)从指针变量fp指向的文件中读…

诺贝尔物理学奖向机器学习与神经网络致敬,科学边界的跨越与未来的启示

2024年诺贝尔物理学奖首次颁发给机器学习与神经网络领域的研究者&#xff0c;这一历史性事件打破了人们对诺贝尔物理学奖的传统认知&#xff0c;激起了全球学术界、科技界的广泛讨论。这一变化不仅标志着科学边界的延伸&#xff0c;也体现出人工智能技术对现实世界的深远影响。…

剪切走的照片:高效恢复与预防策略

一、剪切走的照片现象描述 在日常的数字生活中&#xff0c;照片作为记录生活点滴、工作成果的重要载体&#xff0c;其重要性不言而喻。然而&#xff0c;有时我们可能会遇到一种令人头疼的情况&#xff1a;原本打算通过剪切操作将照片移动到另一个位置&#xff0c;却意外地发现…

Java 8 的内存结构

Java8内存结构图 虚拟机内存与本地内存的区别 Java虚拟机在执行的时候会把管理的内存分配成不同的区域&#xff0c;这些区域被称为虚拟机内存&#xff0c;同时&#xff0c;对于虚拟机没有直接管理的物理内存&#xff0c;也有一定的利用&#xff0c;这些被利用却不在虚拟机内存…

Qt5.15.2静态编译 MinGW with static OpenSSL

如果想用VS2017编译,可参考:Qt5.15.2静态编译 VS2017 with static OpenSSL 一.环境 系统:Windows 10 专业版 64位 编译器:MinGW 8.1.0 第三方工具:perl,ruby和python PS:经验证,用MinGW 12.1.0来编译Qt5.15.2会报错 我用Phthon 2.7.18虽然可以编过,但是强烈建议Pyth…

0.0.0.0 127.0.0.1等几个特殊的IP地址

0.0.0.0 127.0.0.1 localhost 255.255.255.0 255.255.255.255 这都是些什么地址&#xff0c;代表了什么意思。 网络为系统服务器&#xff0c;系统需要网络。 这些地址在系统和网络都存在&#xff0c;作用和意思甚至基本相同。 一、0.0.0.0 在路由中&#xff1a;0.0.0.0表…

【面试宝典】深入Python高级:直戳痛点的题目演示(上)

目录 &#x1f354; 你知道深浅拷⻉的区别吗&#xff1f; &#x1f354; 字典反转&#xff0c;列表反转的实现&#xff1f; &#x1f354; 装饰器是什么&#xff0c;什么场景⽤到装饰器&#xff0c;举个例⼦&#xff1f; &#x1f354; 装饰器的实质是什么…

定时关机(python)

内容 为了更简单地实现定时关机&#xff0c;不必去记繁琐的命令行&#xff0c;于是搞了一个gui出来 基于python和Windows命令行实现&#xff0c;核心为&#xff1a; shutdown -s -t 60 代码 # -*- coding: utf-8 -*- # Environment PyCharm # File_name autoShutdown…

【教学类-36-10】20241010职业抽卡(midjounery-niji)(涂色、裁剪、游戏)

背景需求 昨天在户外玩了角色游戏&#xff0c;受道具所限&#xff08;只有烧烤做饭锅子材料&#xff09;&#xff0c;所有的孩子都只玩了烧烤店、娃娃家做饭的内容&#xff0c;扮演的都是爸妈、厨师等工作 今天从以前的纸类学具中找出一套数量相对较多的“职业涂色卡” 学具代…

2024中国新媒体技术展 | 蓝海创意云vLive虚拟直播即将亮相!

​​ 2024中国新媒体大会由中央宣传部指导&#xff0c;中华全国新闻工作者协会、湖南省人民政府联合主办&#xff0c;旨在推动媒体深度融合发展&#xff0c;促进新闻事业高质量发展&#xff0c;为中国式现代化贡献力量。中国新媒体技术展&#xff08;CMTE&#xff09;是中国新…

设计模式、系统设计 record part05

行为型模式 模板方法模式、解释器模式是类型为模式&#xff0c; 模板方法模式 模板方法&#xff08;Template Method&#xff09; 抽象类&#xff08;Abstract Class&#xff09; 抽象方法&#xff08;Abstract Method&#xff09; 具体方法&#xff08;Concrete Method&#x…

详细解读“霸王面”战术

“霸王面”战术是指在没有得到雇主面试通知的情况下&#xff0c;强行加入面试&#xff0c;以此争取工作机会的求职策略。以下将以3000字左右的篇幅&#xff0c;通过生动形象的例子详细解释这一战术。 一、背景介绍 在当今竞争激烈的就业市场中&#xff0c;求职者需要经历网申…

2.1 App测试与发布指南

欢迎大家订阅【软件测试】 专栏&#xff0c;开启你的软件测试学习之旅&#xff01; 文章目录 前言1 系统架构2 APP测试范围3 APP发布流程4 发布策略 前言 在当今数字化时代&#xff0c;移动应用程序&#xff08;APP&#xff09;和Web应用程序是两种主要的软件交付方式。本文详…

arm imx6ull docker启动失败问题查找与解决 内核配置相关

1、增加POSIX Message qeue&#xff1a;could not get initial namespace: no such file or directory CONFIG_POSIX_MQUEUEy 2、增加namespace failed to set to initial namespace CONFIG_NAMESPACESy 3、创建网络失败&#xff0c;veth配置&#xff1a;docker create endp…