静态工具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中实现该方法:
@override
public 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.处理vo
uservo uservo = beanutil.copyproperties(user, uservo.class);
//转地址vo
if (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层
@override
public 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.转换地址vo
list<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为vo
uservo vo = beanutil.copyproperties(user, uservo.class);
list.add(vo);
// 3.2.转换地址vo
vo.setaddresses(addressmap.get(user.getid()));
}
return list;
}和查询单个用户的区别在于:根据id对查询出来的地址通过map来分组的实现逻辑。
到此这篇关于mybatisplus中静态工具db的实现的文章就介绍到这了,更多相关mybatisplus 静态工具db内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论