当前位置: 首页 > news >正文

MybatisPlus-静态工具DB

目录

静态根据DB

需求一

需求二


静态工具DB

有的时候Service之间也会相互调用,为了避免出现循环依赖问题,MybatisPlus提供一个静态工具类:Db,其中的一些静态方法与IService中方法签名基本一致,也可以帮助我们实现CRUD功能:

循环依赖的定义:

循环依赖(Circular Dependency) 是指 两个或多个组件(类、模块、包、服务等)之间存在直接或间接的相互依赖关系,形成一个闭环,导致系统无法正确初始化、编译或维护。

静态根据DB示例:

@Test
void testDbGet() {User user = Db.getById(1L, User.class);System.out.println(user);
}@Test
void testDbList() {// 利用Db实现复杂条件查询List<User> list = Db.lambdaQuery(User.class).like(User::getUsername, "o").ge(User::getBalance, 1000).list();list.forEach(System.out::println);
}@Test
void testDbUpdate() {Db.lambdaUpdate(User.class).set(User::getBalance, 2000).eq(User::getUsername, "Rose");
}

Db.lambdaQuery(Address.class)中参数位置需要放实体类对象的字节码文件,通过传入实体类的class字节码,拿到字节码就能通过反射拿到实体类的相关信息,从而拿到注解上的信息诸如类名、表名等,以此实现CURD。

示例:

需求一

改造根据id用户查询的接口,查询用户的同时返回用户收货地址列表

(在userService中要注入addressService,需要查询收货地址列表)

首先,我们要添加一个收货地址的VO对象,用于视图返回给前端:

package com.itheima.mp.domain.vo;import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;@Data
@ApiModel(description = "收货地址VO")
public class AddressVO{@ApiModelProperty("id")private Long id;@ApiModelProperty("用户ID")private Long userId;@ApiModelProperty("省")private String province;@ApiModelProperty("市")private String city;@ApiModelProperty("县/区")private String town;@ApiModelProperty("手机")private String mobile;@ApiModelProperty("详细地址")private String street;@ApiModelProperty("联系人")private String contact;@ApiModelProperty("是否是默认 1默认 0否")private Boolean isDefault;@ApiModelProperty("备注")private String notes;
}

然后,改造原来的UserVO,添加一个地址属性,用来存储当前用户的地址列表属性:

@Data
@ApiModel(description = "用户VO实体")
public class UserVO {@ApiModelProperty("用户id")private Long id;@ApiModelProperty("用户名")private String username;@ApiModelProperty("详细信息")private UserInfo info;@ApiModelProperty("使用状态(1正常 2冻结)")private UserStatus status;@ApiModelProperty("账户余额")private Integer balance;@ApiModelProperty("用户的收货地址")private List<AddressVO> addresses;
}

接下来,修改UserController中根据id查询用户的业务接口:

@GetMapping("/{id}")
@ApiOperation("根据id查询用户")
public UserVO queryUserById(@PathVariable("id") Long userId){// 基于自定义service方法查询return userService.queryUserAndAddressById(userId);
}

由于查询业务复杂,所以要在service层来实现。首先在IUserService中定义方法:

import com.baomidou.mybatisplus.extension.service.IService;
import com.itheima.mp.domain.po.User;
import com.itheima.mp.domain.vo.UserVO;public interface IUserService extends IService<User> {void deduct(Long id, Integer money);UserVO queryUserAndAddressById(Long userId);
}

然后,在UserServiceImpl中实现该方法:

	@Overridepublic UserVO queryUserAndAddressById(Long Id) {// 1.查询用户User user = this.getById(Id);if (user == null || user.getStatus()==UserStatus.FROZEN) {throw new RuntimeException("用户状态异常!");}// 2.查询收货地址List<Address> addresses = Db.lambdaQuery(Address.class).eq(Address::getUserId, Id).list();// 3.处理voUserVO userVO = BeanUtil.copyProperties(user, UserVO.class);//转地址VOif (CollUtil.isNotEmpty(addresses)){userVO.setAddresses(BeanUtil.copyToList(addresses,AddressVO.class));}return userVO;}

BeanUtil.copyProperties :

将一个对象的属性值拷贝到另一个已存在的对象中(浅拷贝)。

 BeanUtil.copyToList:

将一个 List<源对象> 拷贝成一个新的 List<目标对象>,每个元素通过  copyProperties  创建新对象,因为是创建新对象,所以是一种深拷贝。

上面两个方法的第二个参数都可以是实体类的字节码,就比如user.class形式的格式,表示在项目运行的时候,会创建一个user的对象去接收源对象的数据,可以避免自己通过NEW关键字去创建对象接收数据。

在上面的代码中,在查询地址时,我们采用了Db的静态方法,因此避免了注入AddressService,减少了循环依赖的风险。即通过DB的lambdaQuery()方法,在参数中放我们要操作的实体类对象,我们可以避免循环依赖的问题,该方法会通过反射获取实体类的相关信息,然后根据我们的条件对当前实体类的表格进行CRUD操作,这种方式避免了注入依赖,也相当于避免了循环依赖。

需求二

根据id批量查询用户,并查询出用户对应的所有地址

controller层

	@GetMapping@ApiOperation("根据id批量查询用户接口")public List<UserVO> queryUserByIds(@ApiParam("用户id集合") @RequestParam("ids") List<Long> ids){return userService.queryUserAndAddressByIds(ids);}

 service层

	@Overridepublic List<UserVO> queryUserAndAddressByIds(List<Long> ids) {// 1.查询用户List<User> users = listByIds(ids);if (CollUtil.isEmpty(users)) {return Collections.emptyList();}// 2.查询地址// 2.1.获取用户id集合List<Long> userIds = users.stream().map(User::getId).collect(Collectors.toList());// 2.2.根据用户id查询地址List<Address> addresses = Db.lambdaQuery(Address.class).in(Address::getUserId, userIds).list();// 2.3.转换地址VOList<AddressVO> addressVOList = BeanUtil.copyToList(addresses, AddressVO.class);// 2.4.用户地址集合分组处理,相同用户的放入一个集合(组)中Map<Long, List<AddressVO>> addressMap = new HashMap<>(0);if(CollUtil.isNotEmpty(addressVOList)) {addressMap = addressVOList.stream().collect(Collectors.groupingBy(AddressVO::getUserId));}// 3.转换VO返回List<UserVO> list = new ArrayList<>(users.size());for (User user : users) {// 3.1.转换User的PO为VOUserVO vo = BeanUtil.copyProperties(user, UserVO.class);list.add(vo);// 3.2.转换地址VOvo.setAddresses(addressMap.get(user.getId()));}return list;}

 和查询单个用户的区别在于:根据id对查询出来的地址通过map来分组的实现逻辑。

http://www.dtcms.com/a/310953.html

相关文章:

  • 在 AKS 中运行 Azure DevOps 私有代理-1
  • 云原生三剑客:Kubernetes + Docker + Spring Cloud 实战指南与深度整合
  • 基于 LFU 策略的存储缓存系统设计与实现
  • 深入 Go 底层原理(八):sync 包的实现剖析
  • Node.js 操作 MongoDB
  • 【机器学习】“回归“算法模型的三个评估指标:MAE(衡量预测准确性)、MSE(放大大误差)、R²(说明模型解释能力)
  • 分布式事务----spring操作多个数据库,事务以及事务回滚还有用吗
  • Oracle 11gR2 Clusterware应知应会
  • 【unity组件_Transform 】
  • 设计模式篇:在前端,我们如何“重构”观察者、策略和装饰器模式
  • 蓝桥杯----串口
  • 内存、硬盘与缓存的技术原理及特性解析
  • 《软件测试与质量控制》实验报告二 单元测试
  • Ubuntu系统VScode实现opencv(c++)视频及摄像头使用
  • 空间平面旋转与xoy平行
  • 【BTC】挖矿
  • MyBatisPlus之CRUD接口(IService与BaseMapper)
  • 【软考中级网络工程师】知识点之堆叠
  • 公网服务器上Nginx或者Openresty如何屏蔽IP直接扫描
  • CS课程项目设计7:基于Canvas交互友好的五子棋游戏
  • 小智服务器Java安装编译(xinnan-tech)版
  • 【05】OpenCV C#——OpenCvSharp 图像基本操作---转灰度图、边缘提取、兴趣区域ROI,图像叠加
  • 28Rsync免密传输与定时备份
  • 【Spring Boot 快速入门】五、文件上传
  • 图漾相机-ROS1_SDK_ubuntu 4.X.X版本编译
  • Shell【脚本 02】离线安装配置Zookeeper及Kafka并添加service服务和开机启动(脚本分析)
  • [硬件电路-122]:模拟电路 - 信号处理电路 - 模拟电路与数字电路、各自的面临的难题对比?
  • [硬件电路-124]:模拟电路 - 信号处理电路 - 测量系统的前端电路详解
  • 编程与数学 03-002 计算机网络 20_计算机网络课程实验与实践
  • filezilla出现connected refused的时候排查问题