mybatis-plus 优雅的写service接口中方法(3)

多表联查

上文讲过了自定义sql ,和wrapper的使用,但是我们可以发现 我们查询的都是数据库中的一张表,那么怎么进行多表联查呢,当然也是用自定义sql来进行实现

比如说  查询 id 为 1  2 4 的用户 并且 地址在北京 的 用户名称 普通的sql查询如下

select  u.username
from  tb_user u,address a where u.id=a.user_id and a.city='北京'  and u.id i
n(1,2,4);

用join on 实现多表的sql为  

select  u.username
from  tb_user u join address a on u.id=a.user_id where  a.city='北京'  and u.id in(1,2,4);

那么 我们如何用mp 来进行改造 自定义sql 来进行多表查询呢

     先用  wrapper 来进行后面 where  条件的拼接  再用自定义sql 拼接

废话不多说 直接上代码  

 然后再usermapper中定义方法 

@Select("SELECT u.* FROM user u INNER JOIN address a ON u.id = a.user_id ${ew.customSqlSegment}")
List<User> queryUserByWrapper(@Param("ew")QueryWrapper<User> wrapper);

service接口

mp不仅对基本的 mapper层进行了接口的封装,还对service层进行了接口的封装,使得 基础的crud也可以直接在controller层直接调用service层直接查询,更加提升了代码的简洁性

而使用Iservice中的方法也很简单  

通常我们有两个  一个是接口service,一个是实现接口的实现类     我们只需要让接口继承 iservice,然后让自己的实现类 实现自己的接口,并且继承serviceimpl   废话不多说  我们直接上代码

其中User是对应的数据库实体类   ,同样Usermapper 也是  

 但是我们这样说是显得太过宽泛  我们直接上例子 对service接口进行测试

接口测试

我们 假如说  现在有一个需求   根据用户的id 来进行扣减用户的余额   ,而在用户表中有一个状态  只有状态正常的

并且余额充足的才能进行余额的扣减    

现在 我们在 Usercontroller 中定义 一个方法

//根据id扣除余额
    @PutMapping("/{id}/deduction/{money}")
    void deductMoney(@PathVariable Long id,
                     @PathVariable Integer money){
        myService.deductMoney(id,money);
    }

然后是 userservice接口

package com.itheima.mp.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.itheima.mp.domain.po.User;

public interface IUserService extends IService<User> {
    void deductBalance(Long id, Integer money);
}

最后是实现类

package com.itheima.mp.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.mp.domain.po.User;
import com.itheima.mp.mapper.UserMapper;
import com.itheima.mp.service.IUserService;
import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
    @Override
    public void deductBalance(Long id, Integer money) {
        // 1.查询用户
        User user = getById(id);
        // 2.判断用户状态
        if (user == null || user.getStatus() == 2) {
            throw new RuntimeException("用户状态异常");
        }
        // 3.判断用户余额
        if (user.getBalance() < money) {
            throw new RuntimeException("用户余额不足");
        }
        // 4.扣减余额
        baseMapper.deductMoneyById(id, money);
    }
}

 mapper中的实现接口为  

@Update("UPDATE user SET balance = balance - #{money} WHERE id = #{id}")
void deductMoneyById(@Param("id") Long id, @Param("money") Integer money);

但是 但是这样是否有点不太优雅   那么  我们怎么把他变得优雅? 来  让我们改造一下

优雅的接口测试

首先  我们可以看到 在 我们对比用户状态的时候 用户状态异常的数字是写死的,这样写有没有问题,没有问题,但是假如我们以后用了多个用户状态的的数字,以后想改 是不是特别 的麻烦  ,所以我们干脆定义一个枚举类型,来进行 用户状态的对比

我们原来user实体类中的类型 是 

是interger类型的对比 ,下面 我们 定义一个如下的枚举   

 并在mp的yaml文件中配置枚举处理器

mybatis-plus:
  configuration:
    default-enum-type-handler: com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler

配置好 之后再把user实体类中的 状态的类型 改成 枚举类型     

好,那么现在我们来解释一下  枚举类型中的注解  

使用enumvalue 注解,代表着  枚举类中的哪个值 作为 数据库status字段的值    

比如说   我们  数据库中定义的字段status为  int类型的,然后我们对应的数据库user表的实体类user 的类型是 枚举类型的这样就会导致我们在查询插入的时候出现类型转换的错误,我们加上这个注解,开启配置枚举处理器,就可以 实现二者值之间的自动转换  

下面 我们来 写一个例子

@PostMapping
    void   userSelect(@Param("id") Long id){
//通过枚举类型 加用户id进行查询
    LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<User>().eq(User::getId, id).eq(User::getStatus, UserStatus.NORMAL);
    User user1 = myService.getBaseMapper().selectOne(wrapper);
    System.out.println(user1);

    //使用枚举类型插入用户

    User user = new User();
//我们着重看这一行 setstatus
    user.setStatus(UserStatus.NORMAL);
    user.setUsername("wang");
    user.setPassword("123456");
    UserInfo userInfo = new UserInfo();
    userInfo.setAge(1);
    userInfo.setGender("22");
    userInfo.setIntro("6666666");
    user.setInfo(userInfo);
    myService.save(user);
}

 下面我们用apifox进行测试  

可以看到  用了enumvalue注解  已经成功的把枚举类型转换成数据库类型了,是不是灰常的优雅

优雅的json处理器

在上文中我们看到 怎么还有个userinfo 那玩意是什么鬼 ,下面我们来解释一下 

 在数据库中 我们的info字段定义的是一个json类型

但是 在我么们user实体类中确实 一个string类型的 字段  ,在我们插入的时候 会非常的麻烦 我们需要把字符串类型写成类似于json类型进行插入,这样太麻烦   

我们  直接可以定义一个json类型的实体类 ,然后把user实体类的类型换成该json类型的实体类 ,然后再user实体类字段上加上json类型处理器的注解  就可以完成转换

@Data
@AllArgsConstructor(staticName = "set")
@NoArgsConstructor
public class UserInfo {
    private Integer age;
    private  String intro;
    private  String gender;
}

这样我们再插入的时候 就可以完成 json类型之间的转换了

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

AI崛起,掌握它,开启智能新生活!

AI崛起&#xff0c;掌握它&#xff0c;开启智能新生活&#xff01; &#x1f604;生命不息&#xff0c;写作不止 &#x1f525; 继续踏上学习之路&#xff0c;学之分享笔记 &#x1f44a; 总有一天我也能像各位大佬一样 &#x1f3c6; 博客首页 怒放吧德德 To记录领地 &…

LDAP: error code 32 - No Such Object

目前我的项目版本&#xff1a; Spring版本:5.3.15SpringBoot版本:2.6.3 完整错误 org.springframework.ldap.NameNotFoundException: [LDAP: error code 32 - No Such Object]; nested exception is javax.naming.NameNotFoundException: [LDAP: error code 32 - No Such Objec…

Java进阶学习笔记9——子类中访问其他成员遵循就近原则

正确访问成员的方法。 在子类方法中访问其他成员&#xff08;成员变量、成员方法&#xff09;&#xff0c;是依照就近原则的。 F类&#xff1a; package cn.ensource.d13_extends_visit;public class F {String name "父类名字";public void print() {System.out.p…

[算法][前缀和] [leetcode]724. 寻找数组的中心下标

题目地址 https://leetcode.cn/problems/find-pivot-index/description/ 题目描述 代码 class Solution {public int pivotIndex(int[] nums) {int total Arrays.stream(nums).sum();//前缀和int prefixSum 0;int len nums.length;for(int i 0;i<len;i){if (i-1>0){p…

【已解决】C#设置Halcon显示区域Region的颜色

前言 在开发过程中&#xff0c;突然发现我需要显示的筛选区域的颜色是白色的&#xff0c;如下图示&#xff0c;这对我们来说不明显会导致我的二值化筛选的时候存在误差&#xff0c;因此我们需要更换成红色显示这样的话就可以更加的明显&#xff0c;二值化筛选更加的准确。 解…

若依 Ruoyi-Vue PageHelper 分页失效 total为记录数

分页插件PageHelper返回记录总数total竟然出错了 执行控制台的SQL&#xff0c;查询出来的total数量是对的&#xff0c;很奇怪分页的total设置为查询到的记录数。 怀疑对list.stream操作&#xff0c;影响了分页&#xff0c;代码发现确实是这样&#xff0c;debug&#xff0c;居然…

【Mac】跑猫RunCat for mac(菜单栏Cpu可视化监测工具) v10.3免费版安装教程

软件介绍 RunCat是一款为菜单栏提供关键帧动画的软件。动画速度会根据Mac的CPU使用情况而变化。奔跑的小猫通过运行速度告诉您Mac的CPU使用率。 这是一款好玩的软件&#xff0c;可以为您的Mac使用添加一点小确幸。感兴趣的朋友可以试试哦。 安装步骤 1.打开安装包&#xff0…

idea 出现 cpu占用100%

一、IDEA的CPU占用率过高 二、解决办法 idea安装路径bin目录 修改idea64.exe.vmoptions配置文件 原来的 -Xms128m -Xmx750m -XX:ReservedCodeCacheSize240m -XX:UseConcMarkSweepGC -XX:SoftRefLRUPolicyMSPerMB50 修改为(IDEA优化内存配置) -Xms2048m -Xmx4096m -XX:Reser…

SpringCloudAlibaba:6.3SpringBoot接入RocketMQ

依赖 <?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 htt…

C++入门:从C语言到C++的过渡(2)

目录 1.缺省参数 1.1缺省参数的概念 1.2缺省参数的分类及使用 1.3注意点 2.函数重载 2.1函数重载的定义 2.2函数重载的情况分类 2.3注意 2.4函数名修饰规则 3.引用 3.1引用的概念 3.2注意事项 3.3常引用 4.4引用的使用场景 4.4.1作为函数的参数 4.4.2做函数返回…

等保三级 腾讯云控制台检查项设置

1、地址限制 2、角色里加三权用户&#xff08;查看日志权限&#xff09; 3、登录失败处理和超时退出 4、密码复杂度和口令有效期 5、双因素验证 6、操作审计

怎么快速批量导出文本二维码?文件批量生码的方法和步骤

随着互联网的快速发展&#xff0c;二维码的应用也越来越广泛&#xff0c;现在很多二维码会用来展示物品信息&#xff0c;将编辑好的文字内容生成二维码之后&#xff0c;让其他人通过扫码的方式来获取相关内容。那么当有多条信息时&#xff0c;有什么方法能够一次批量生成二维码…

ctfhub中的SSRF的相关例题(下)

目录 URL Bypass 知识点 相关例题 数字IP Bypass 相关例题 方法一&#xff1a;使用数字IP 方法二&#xff1a;转16进制 方法三&#xff1a;用localhost代替 方法四&#xff1a;特殊地址 302跳转 Bypass ​编辑 关于localhost原理: DNS重绑定 Bypass 知识点&…

第 398 场 LeetCode 周赛题解

A 特殊数组 I 模拟&#xff1a;遍历数组判断是否是一个特殊数组 class Solution { public:bool isArraySpecial(vector<int>& nums) {int r 0;while (r 1 < nums.size() && nums[r 1] % 2 ! nums[r] % 2)r;return r nums.size() - 1;} };B 特殊数组 I…

打包要求 minCompileSdk 使用指定版本及以上

我当前的 compileSdkVersion 30&#xff0c;因为依赖了 androidx.core:core:1.9.0 它要求最低 compileSdkVersion 33。 那么如果我不想升级 compileSdkVersion 应该怎么办&#xff1f; 答&#xff1a;当然是降低 core:core 版本&#xff01; 看看谁依赖了这两个版本 android…

SpringCloud微服务04-Elasticsearch-DSL查询-聚合

一、Elasticsearch 搜索引擎&#xff0c;响应速度非常快&#xff0c;特别是对大数据量的情况 1.初始elasticsearch 如果只需要商品搜索&#xff0c;百度这种搜索网站&#xff0c;只需要第二个就够了 docker部署&#xff1a;day08-Elasticsearch - 飞书云文档 (feishu.cn) e…

有趣的css - 移形换位加载动画

大家好&#xff0c;我是 Just&#xff0c;这里是「设计师工作日常」&#xff0c;今天分享的是一个移形换位动态加载小动效&#xff0c;适用于 app 列表加载&#xff0c;页面加载或者图片懒加载等场景。 最新文章通过公众号「设计师工作日常」发布。 目录 整体效果核心代码html…

python基础之循环

目录 1.while 循环 2.for循环 3.for-else 和 while-else 4.关键字break和continue 1.while 循环 语法结构 while 条件语句:代码 解释&#xff1a;不断循环&#xff0c;如果条件语句为真&#xff0c;则执行代码&#xff0c;直到条件语句为假。假设条件语句一直为真&#xff0…

智能体(Agent)详细精讲

1.什么是智能体 智能体&#xff08;Agent&#xff09;是一种由大规模语言模型&#xff08;如GPT-4或本地模型&#xff09;驱动的先进系统&#xff0c;能够执行多种复杂任务。通过引入智能体&#xff0c;企业和个人可以实现自动化处理和高效管理各种事务。 智能体的核心是其“大…

ATmega328P加硬件看门狗MAX824L看门狗

void Reversewdt(){ //硬件喂狗&#xff0c;11PIN接MAX824L芯片WDIif (digitalRead(11) HIGH) {digitalWrite(11, LOW); //低电平} else {digitalWrite(11, HIGH); //高电平 }loop增加喂狗调用 void loop() { …… Reversewdt();//喂狗 }