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中定义方法

sql 复制代码
@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 中定义 一个方法

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

然后是 userservice接口

java 复制代码
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);
}

最后是实现类

java 复制代码
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中的实现接口为

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

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

优雅的接口测试

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

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

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

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

java 复制代码
mybatis-plus:
  configuration:
    default-enum-type-handler: com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler

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

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

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

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

下面 我们来 写一个例子

java 复制代码
@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类型处理器的注解 就可以完成转换

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

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

相关推荐
2401_8712133026 分钟前
mysql之MHA
数据库·mysql
言之。39 分钟前
【MySQL】事务
数据库·mysql
潇湘秦1 小时前
Oracle 11G还有新BUG?ORACLE 表空间迷案!
数据库·oracle
阿moments1 小时前
SpringBoot3-第十篇(整合Web安全)
spring boot·安全·web安全
凡人的AI工具箱1 小时前
每天40分玩转Django:Django Email
数据库·人工智能·后端·python·django·sqlite
后端转全栈_小伵1 小时前
SQLite本地数据库的简介和适用场景——集成SpringBoot的图文说明
数据库·spring boot·后端·sqlite·学习方法
鹿屿二向箔2 小时前
基于SSM(Spring + Spring MVC + MyBatis)框架构建一个图书馆仓储管理系统
spring·mvc·mybatis
李长渊哦2 小时前
使用 Spring Boot 实现文件上传:从配置文件中动态读取上传路径
java·spring boot·spring
积极向上的Elbert2 小时前
Mybatis-Plus中的Page方法出现Records的值大于0但是total的值一直是0
java·开发语言·mybatis
猿来入此小猿2 小时前
基于SpringBoot在线音乐系统平台功能实现十七
java·spring boot·后端·毕业设计·音乐系统·音乐平台·毕业源码