今天深入的学习了一下mp,从头开始学习!哈哈哈哈哈

本节只讲干的!

我们上来先看一段代码,不知道你能不能看明白!

package com.itheima.mp.mapper;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.itheima.mp.domain.po.User;
import com.itheima.mp.domain.po.UserInfo;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;@SpringBootTest
class UserMapperTest {@Autowiredprivate UserMapper userMapper;@Testvoid testInsert() {User user = new User();
//        user.setId(5L);user.setUsername("hanMeiMei");user.setPassword("123");user.setPhone("18688990011");user.setBalance(200);user.setInfo(UserInfo.of(24, "英文老师", "female"));user.setCreateTime(LocalDateTime.now());user.setUpdateTime(LocalDateTime.now());userMapper.insert(user);}@Testvoid testSelectById() {User user = userMapper.selectById(5L);System.out.println("user = " + user);}@Testvoid testQueryByIds() {List<User> users = userMapper.selectBatchIds(List.of(1L, 2L, 3L, 4L));users.forEach(System.out::println);}@Testvoid testUpdateById() {User user = new User();user.setId(5L);user.setBalance(20000);userMapper.updateById(user);}@Testvoid testDeleteUser() {userMapper.deleteById(5L);}@Testvoid testQuery() {//1.构造查询条件QueryWrapper<User> userQueryWrapper = new QueryWrapper<User>().select("id", "username", "info", "balance").like("username", "o").ge("balance", 1000);//查询List<User> users = userMapper.selectList(userQueryWrapper);System.out.println("users = " + users);}@Testvoid testUpdate() {//1.要更新的数据User user = new User();user.setBalance(2000);// 2. 构造更新条件QueryWrapper<User> userQueryWrapper = new QueryWrapper<User>().eq("username", "jack");userMapper.update(user, userQueryWrapper);}@Testvoid testUpdateWrapper() {//1.List<Long> ids = new ArrayList<>();ids.add(1L);ids.add(2L);ids.add(4L);UpdateWrapper<User> wrapper = new UpdateWrapper<User>().setSql("balance = balance-200").in("id", ids);//3.userMapper.update(null, wrapper);}@Testvoid testCustomSqlUpdate() {List<Long> ids = new ArrayList<>();ids.add(1L);ids.add(2L);ids.add(4L);int amount = 200;//2.定义条件QueryWrapper<User> wrapper = new QueryWrapper<User>().in("id", ids);userMapper.updateBalance(wrapper, amount);}@Testvoid testCustomSqlSelect() {QueryWrapper<User> userQueryWrapper = new QueryWrapper<User>().eq("username", "jack").select("id", "username", "info", "balance");userMapper.selectList(userQueryWrapper);}
}

这是一个测试类,里面写的都是mapper的代码!大概解释一下,就是mp既可以用在service层,也可以用在mapper层,但是呢,公司常用的是mapper层的东西,我只是写着玩一下mapper层的东西,熟悉一下!mapper的查询用的是querywrapper,可以用mapper进行增删改查操作!

我们一直用mapper层进行增上改查的操作,其实很多公司是并不允许的,所以我们选择用service层进行操作!

package com.itheima.mp.service;import com.baomidou.mybatisplus.extension.service.IService;
import com.itheima.mp.domain.dto.PageDTO;
import com.itheima.mp.domain.po.User;
import com.itheima.mp.domain.query.PageQuery;
import com.itheima.mp.domain.query.UserQuery;
import com.itheima.mp.domain.vo.UserVO;import java.util.List;public interface IUserService extends IService<User> {void deduchMoney(Long id, Integer money);List<User> quertUsers(String name, Integer status, Integer minBalance, Integer maxBalance);void updateUserId(Long id, Integer money);UserVO queryUserAndAddressById(Long id);List<UserVO> queryUserAndAddressByIds(List<Long> ids);PageDTO<UserVO> queryUserAndAddressByPage(UserQuery page);
}

首先,我们的service层需要继承IService这个东西,然后写上实体类,这样就可以利用反射查询到你的数据库!这样就可以用mp的一些操作了

我们先来简单的解释一些代码!

@PostMapping@ApiOperation("新增用户信息")public void saveUser(@RequestBody UserFormDTO userFormDTO) {//1.把dto拷贝到实体po对象User user = BeanUtil.copyProperties(userFormDTO, User.class);userService.save(user);}

save这个一看就是保存操作,用service进行一个保存的操作,前端传过来DTO,然后后端进行存储,直接这样就可以,很方便~

    @DeleteMapping("{id}")@ApiOperation("删除用户信息")public void deleteUserById(@ApiParam("用户id") @PathVariable Long id) {userService.removeById(id);}

removeById这个就是根据id删除操作,很简答!

@GetMapping("{id}")@ApiOperation("按照id查询用户信息")public UserVO SelectUserById(@ApiParam("用户id") @PathVariable Long id) {userService.getById(id);}

这个就是根据单个id查询用户操作!

@GetMapping@ApiOperation("查询用户信息")public List<UserVO> SelectQueryUserById(@ApiParam("用户id集合") @RequestParam("ids") List<Long> ids) {List<User> users = userService.listByIds(ids);return BeanUtil.copyToList(users, UserVO.class);}

这个就是根据id集合然后去查询你的用户信息操作!

然后我们上点难度奥!不能总弄那个增删改查!

需求:前端传过来一个id和money,要求让这个id的用户扣钱!

所以我们controller层就不能直接用mp自带的操作了,这时候我们需要自定义一个service去写!

 @PutMapping("/{id}/deduction")@ApiOperation("扣减用户余额")public void updateUserId(@ApiParam("用户id") @PathVariable Long id,@ApiParam("金额") @PathVariable Integer money) {userService.updateUserId(id, money);}

这样我们就拿到了id和money,然后去更新操作,我们看一下Impl实现类!

  @Override@Transactionalpublic void updateUserId(Long id, Integer money) {//1.查询用户User user = this.getById(id);//2.校验状态if (user == null || user.getStatus() == UserStatus.FROZEN) {throw new RuntimeException("用户不存在或者被冻结");}//3.校验余额是否充足if (user.getBalance() < money) {throw new RuntimeException("余额不足");}//4.减去余额int remainBalance = user.getBalance() - money;lambdaUpdate().set(User::getBalance, remainBalance).set(remainBalance == 0, User::getStatus, UserStatus.FROZEN).eq(User::getId, id).update();}

我们先利用id去查询这个用户,然后对这个用户进行校验,还要对金额进行一个校验!

最后我们在减去剩余的钱,然后set到这个用户的balance里面!

这里面大家可能看着有一点蒙,这两个位置我需要解释一下,第一个condition,就是条件,这里可以实现一个操作!就是当剩余的金额是0的时候,我们的状态就要变成冻结了!因为他钱都不够了,肯定冻结他。这里还涉及到一个操作就是mp对枚举类型的操作!

我们的status这种一般就会定义出来一个枚举,因为只有2种状态,所以定义枚举是一个非常好的选择!我们定义完枚举后,我们还需要去对应的po里面把这个字段的类型改了!

处理枚举与数据库类型自动转换,我们必须告诉mp,枚举中的哪个字段的值作为数据库值。mp提供了@EnumValue注解来标记枚举属性,然后我们还需要去yml里面去配置一下!

这样我们查询出来的就是枚举的类型了,但是我们想查出来desc的值,这个mp也提供了一个注解

红色箭头:标注为mp被数据库识别的属性。蓝色箭头:标注为返回的字段!

这样的一个更新的操作基本上就完成了!我们再看一下完整代码

  @Override@Transactionalpublic void updateUserId(Long id, Integer money) {//1.查询用户User user = this.getById(id);//2.校验状态if (user == null || user.getStatus() == UserStatus.FROZEN) {throw new RuntimeException("用户不存在或者被冻结");}//3.校验余额是否充足if (user.getBalance() < money) {throw new RuntimeException("余额不足");}//4.减去余额int remainBalance = user.getBalance() - money;lambdaUpdate().set(User::getBalance, remainBalance).set(remainBalance == 0, User::getStatus, UserStatus.FROZEN).eq(User::getId, id).update();}

再来一个新的需求,我们常常能碰到这样的事情,就是用户进行搜索,它可以输入3-4个字段,但是用户又不一定全填,所以我们就需要做好几个的非空判断的模糊查询!这样比较烦!我们来用mp实现一下这个效果!

我们直接看一下service,这里就是前面是条件,然后后面是查询出来的东西,这样就可以实现这个操作了!非常简单!

接下来我就又碰到了一个问题,就是我们有些字段可能是json的,但是我们实体类里面写的都是String类型,所以这样就导致我们在service里面拿不到这个值!mp也提供了这样的方法!

我们首先定义一个实体类去装这个json对象!

然后在实体类里面需要添加2个注解,一个是@TableName,另一个是@TableField

这样就看到,我们的json数据可以被正常的返回了!

现在又有一个新的需求!

我们有两张表,一张是用户表,一张是地址表!

这里面能看到我们是利用用户的id和地址表的user_id进行关联的!

我想查询出一个用户的所有收货地址!这个操作!!

我们先思考这个操作!首先,返回的一定是一个vo,然后我们的uservo里面要包含address的vo!也就是一个嵌套的操作!

我们先定义好这个vo,然后进行操作!

@GetMapping("/userList")@ApiOperation("查询用户信息")public List<UserVO> SelectQueryUserByIds(@ApiParam("用户id集合") @RequestParam("ids") List<Long> ids) {return userService.queryUserAndAddressByIds(ids);}

我们先看一下controller,前端传给我们一个id的集合,可能要查询好几个用户的地址!

我们要返回一个list集合给前端!

我们来看一下service层!首先我们要根据前端传过来的用户id,查询出所有的用户,放到一个List里面!接下来我们把查询出来的所有用户的id放到一个集合里面userIds!

这里面引入一个Db的知识,只有在3.5.3 以上版本的mp才可以使用!Db.lamdbaQuery这样可以避免循环依赖,Db可以不用注入service就直接使用!

我们利用Db,查询出所有用户id的地址放入到list集合里面!然后把地址的po转成vo!

然后这里面有一个操作!就是我们要写一个addressMap,因为我们需要将相同用户的地址放入到一个集合里面!我们用stream流进行操作!我们最终返回的Map就是<用户id,用户地址集合>这样的一个map!

然后我们最终还是要返回一个UserVO的一个集合,然后我们进行一个循环,让user的po转成vo后放入用户的地址在userVO中,最后返回这个list即可!这个操作就做完了!!

我们还得讲一下分页查询问题!

分页查询mp是需要封装一个MybatisConfig的!

package com.itheima.mp.config;import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class MybatisConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {// 初始化核心插件MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();// 添加分页插件interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));return interceptor;}
}

封装好了后,我们提出一个需求!我们首先需要返回一个这样数据结构的东西!

{"total": 100006,"pages": 50003,"list": [{"id": 1685100878975279298,"username": "user_9****","info": {"age": 24,"intro": "英文老师","gender": "female"},"status": "正常","balance": 2000}]
}

我们首先需要封装一个pageQuery和PageDTO这两个东西!

package com.itheima.mp.domain.query;import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.ApiModel;
import lombok.Data;@Data
@ApiModel(description = "分页查询条件实体")
public class PageQuery {private Integer pageNo = 1;private Integer pageSize = 5;private String sortBy;private Boolean isAsc = true;public <T> Page<T> toMpPage(OrderItem... orders) {// 1.分页条件Page<T> p = Page.of(pageNo, pageSize);// 2.排序条件// 2.1.先看前端有没有传排序字段if (sortBy != null) {p.addOrder(new OrderItem(sortBy, isAsc));return p;}// 2.2.再看有没有手动指定排序字段if (orders != null) {p.addOrder(orders);}return p;}public <T> Page<T> toMpPage(String defaultSortBy, boolean isAsc) {return this.toMpPage(new OrderItem(defaultSortBy, isAsc));}public <T> Page<T> toMpPageDefaultSortByCreateTimeDesc() {return toMpPage("create_time", false);}public <T> Page<T> toMpPageDefaultSortByUpdateTimeDesc() {return toMpPage("update_time", false);}
}

PageDTO

package com.itheima.mp.domain.dto;import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.ApiModel;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.util.Collections;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;@Data
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(description = "分页结果实体")
public class PageDTO<V> {private Long total;private Long pages;private List<V> list;/*** 返回空分页结果* @param p MybatisPlus的分页结果* @param <V> 目标VO类型* @param <P> 原始PO类型* @return VO的分页对象*/public static <V, P> PageDTO<V> empty(Page<P> p){return new PageDTO<>(p.getTotal(), p.getPages(), Collections.emptyList());}/*** 将MybatisPlus分页结果转为 VO分页结果* @param p MybatisPlus的分页结果* @param voClass 目标VO类型的字节码* @param <V> 目标VO类型* @param <P> 原始PO类型* @return VO的分页对象*/public static <V, P> PageDTO<V> of(Page<P> p, Class<V> voClass) {// 1.非空校验List<P> records = p.getRecords();if (records == null || records.size() <= 0) {// 无数据,返回空结果return empty(p);}// 2.数据转换List<V> vos = BeanUtil.copyToList(records, voClass);// 3.封装返回return new PageDTO<>(p.getTotal(), p.getPages(), vos);}/*** 将MybatisPlus分页结果转为 VO分页结果,允许用户自定义PO到VO的转换方式* @param p MybatisPlus的分页结果* @param convertor PO到VO的转换函数* @param <V> 目标VO类型* @param <P> 原始PO类型* @return VO的分页对象*/public static <V, P> PageDTO<V> of(Page<P> p, Function<P, V> convertor) {// 1.非空校验List<P> records = p.getRecords();if (records == null || records.size() <= 0) {// 无数据,返回空结果return empty(p);}// 2.数据转换List<V> vos = records.stream().map(convertor).collect(Collectors.toList());// 3.封装返回return new PageDTO<>(p.getTotal(), p.getPages(), vos);}
}

这两个东西封装完了,我们来看代码!

红色箭头就是我们封装好的Pagequery,这个UserQuery是继承了Pagequery的,所以我们这个方法就是根据更新时间排序!

然后绿色箭头就是我们的查询条件,最后发挥一个VO即可,这个分页查询其实都是封装好的!

最后分享一个插件我觉得非常好用!

这个可以直接使用生成代码!第一个是连接数据库,第二个是生成代码!

你只要调整好文件,包...等等一切操作,他都可以帮你生成,但是逻辑你还是要自己写的,哈哈哈哈哈哈!

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

安卓9.0系统修改定制化____安卓9.0系统精简 了解系统app组件构成 系统app释义 常识篇 一

在安卓 9.0 系统的使用过程中,许多用户都希望能够对系统进行深度定制,让手机系统更加贴合个人需求。而系统精简作为定制化的重要一环,不仅能够释放手机存储空间,还能提升系统运行速度,优化资源分配。想要安全有效地对安卓 9.0 系统进行精简,深入了解系统 app 组件的构成是…

2.4 Windows Conan编译FFmpeg 4.4.1

Conan的安装与使用参考之前的文章&#xff1a;Conan简单使用 一、Conan编译ffmpeg 1.1 Conan的配置文件 创建配置文件&#xff1a;C:\Users\wujh\.conan2\profiles\vs2019 [settings] archx86_64 build_typeRelease compilermsvc compiler.cppstd14 compiler.runtimedynami…

社群经济视域下开源链动2+1模式与AI智能名片赋能S2B2C商城小程序的创新发展研究

摘要&#xff1a;在数字经济蓬勃发展的背景下&#xff0c;社群经济作为连接用户情感与价值反哺的新型经济形态&#xff0c;正通过技术创新与模式重构实现深度演化。本文基于社群经济“创造有价值连接”的本质特征&#xff0c;系统探讨“开源链动21模式”“AI智能名片”与“S2B2…

【计算机网络】——reactor模式高并发网络服务器设计

&#x1f525;个人主页&#x1f525;&#xff1a;孤寂大仙V &#x1f308;收录专栏&#x1f308;&#xff1a;计算机网络 &#x1f339;往期回顾&#x1f339;&#xff1a;【计算机网络】非阻塞IO——epoll 编程与ET模式详解——(easy)高并发网络服务器设计 &#x1f516;流水不…

Uniapp跨端兼容性全方位解决方案

在当今多端融合的移动互联网时代&#xff0c;Uniapp作为一款优秀的跨平台开发框架&#xff0c;已成为许多开发者的首选。然而&#xff0c;真正的挑战在于如何优雅地处理不同平台之间的差异。本文将全面剖析Uniapp跨端开发的兼容性处理方案&#xff0c;提供从基础到高级的完整解…

迅为RK3576开发板NPUrknn-toolkit2环境搭建和使用docker环境安装

开发板采用核心板底板结构&#xff0c;在我们的资料里提供了底板的原理图工程以及PCB工程&#xff0c;可以实现真正意义上的裁剪、定制属于自己的产品&#xff0c;满足更多应用场合。 迅为针对RK3576开发板整理出了相应的开发流程以及开发中需要用到的资料&#xff0c;并进行详…

什么是 OpenFeigin ?微服务中的具体使用方式

什么是Feign&#xff1f; Feign 是一种声明式的 HTTP 客户端框架&#xff0c;主要用于简化微服务架构中服务之间的远程调用&#xff0c;也可以通过定义接口和注解的方式调用远程服务&#xff0c;无需手动构建 HTTP 请求或解析响应数据。Spring Cloud 对 Feign 进行了增强&…

对抗性提示:进阶守护大语言模型

人工智能模型正快速进化 —— 变得更具帮助性、更流畅&#xff0c;并且更深入地融入我们的日常生活和商业运营中。但随着其能力的提升&#xff0c;风险也在增加。在维护安全可信的人工智能方面&#xff0c;最紧迫的挑战之一是对抗性提示&#xff1a;这是一种微妙且通常富有创意…

运营商频段

以下是三大运营商&#xff08;中国移动、中国电信、中国联通&#xff09;及中国广电的 5G 主要频段 及其所属运营商的整理表格&#xff1a; 运营商频段上行频率 (MHz)下行频率 (MHz)带宽备注广电n28703-733758-788230MHz移动共享n794900-4960-60MHz-移动n412515-2675-160MHz-n7…

项目拓展-Apache对象池,对象池思想结合ThreadLocal复用日志对象

优化日志对象创建以及日志对象复用 日志对象上下文实体类 traceId 请求到达时间戳 请求完成时间戳 请求总共耗费时长 get/post/put/delete请求方式 Http状态码 原始请求头中的所有键值对 请求体内容 响应体内容 失败Exception信息详细记录 是否命中缓存 package c…

Javaweb - Vue入门

Vue是一款用于构建用户界面的渐进式的JavaScript框架。 使用步骤 引入Vue模块&#xff0c;创建Vue的应用实例&#xff0c;定义元素&#xff0c;交给Vue控制。 一、引入Vue模块 因为使用的是模块化的JavaScript&#xff0c;因此在script标签内要声明一个属性&#xff1a;typ…

C++ 标准模板库各个容器的应用场景分析

C 标准模板库&#xff08;STL&#xff09;中的容器分为序列式容器、关联式容器和无序容器&#xff0c;各自适用于不同场景。以下是主要容器的应用场景及案例&#xff1a; 一、序列式容器 元素按插入顺序存储&#xff0c;支持线性访问。 1. vector 场景&#xff1a;动态数组…

安装前端vite框架,后端安装fastapi框架

前期准备 首先新建一个文件夹&#xff0c;文件夹里面新建一个文件夹&#xff0c;用于安装依赖 安装vite框架 npm init -y 目的是安装package.json配置文件 npm install vite --save-dev 安装vite框架 安装完是这个样子 新建了一个文件夹和js文件 后端内容 main.js document.…

深度学习:基础与概念(第1章:深度学习革命)

目录 第1章&#xff1a;深度学习革命 1.1深度学习的影响 1.1.1医疗诊断 1.1.2蛋白质结构预测 1.1.3图像合成 1.1.4大语言模型 1.2一个教学示例 1.2.1合成数据 1.2.2线性模型 1.2.3误差函数 1.2.4模型复杂度 1.2.5正则化 1.2.6模型选择 1.3机器学习简史 1.3.1单层…

通过触发器统计访问数据库的客户端IP地址

通过触发器统计访问数据库的客户端IP地址 创建用户登录审计表创建登录审计触发器查看登录审计结果禁用和启用触发器创建用户登录审计表 创建记录表: create table appuser1.user_login_audit (login_time DATE,session_id number,username VARCHAR2(30),os_user VARCHAR2(30…

在MCU上的1微秒的延迟实现方案及测量方法

运行环境&#xff1a; stm32h743iit6; 主频480MHz; APB1; 240MHz; TIM5 240MHz; 预分频系数为1; 定时器计数频率240MHz&#xff1b; 应用需求&#xff1a;实现软件模拟IIC&#xff0c;延迟精度2个微秒&#xff1b; 量变引起质变&#xff0c;当延迟粒度太小时&#xff0c;需要考…

macos电脑本地搭建mistral-7b大模型出现4-bit量化和缓存不足问题的记录

问题背景 本人想再本地笔记本电脑上搭建一个mistral-7b的大模型&#xff0c;在搭建的过程中&#xff0c;出现了4-bit量化模式无法处理的问题&#xff0c;以及电脑内存/显存不足的问题&#xff0c;导致无法搭建 电脑硬件信息 名称&#xff1a;2019 Mac book pro 内存&#xff1a…

C# 基础知识总结(带详细文字说明)

1. 基础语法结构 C# 程序由命名空间、类和方法组成。每个程序必须有一个 Main 方法作为入口点。using 指令用于导入命名空间&#xff0c;Console.WriteLine() 是常用的输出方法。 csharp 复制 下载 using System; // 引入核心命名空间class Program // 类定义 {static v…

C#最佳实践:为何要统一命名

C#最佳实践:为何要统一命名 在 C# 编程的世界里,代码就像是一座庞大的数字城市,而命名则是城市中纵横交错的街道名称与建筑标识。如果没有统一的命名规范,这座城市将陷入混乱,开发者在其中探索、维护代码时也会迷失方向。统一命名不仅是一种编程习惯,更是保障代码质量、…

通过后端连接Opengauss数据库的方法

文章目录 通过后端连接Opengauss数据库的方法一、为什么默认不能访问&#xff1f;二、要让普通用户从宿主机访问数据库&#xff0c;需要以下几个步骤&#xff1a;1. 使用 omm 超级用户登录数据库2. 创建一个应用程序专用用户&#xff0c;并设置密码3. 提供给应用程序专用用户对…