按照之前的内容,我们已经基本搭建起来一个项目的雏形,按照UserService的那一个模板,结合数据库的设计就可以逐渐增加项目功能。但是在实际生产中,我们为了完成一个复杂功能,经常需要同时从多个表里查询数据,这时候我们的Service层就不会像规划的那样清晰了,要不把综合查询方法写在一个主要的Service中,要不就单独开辟一套流程模板。按照DDD的思想,这两种其实都不是太好,领域界限不够清晰了,从技术层面上讲,springboot中的多个Service也出现了互相引用导致的循环注入问题,就是几个Service中都有对同一个对象的@Autowired。MyBatis-Plus也早已帮我们想到了这些问题,它提供了一个静态方法类,可以直接跳过Service层来查询表数据。
1、创建一个新的类Project,对应新表。
package com.mj.mybatisplus.po;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.io.Serializable;
@TableName("project")
@Data
public class Project implements Serializable {
@TableId(value = "id",type = IdType.AUTO)
private Integer id;
@TableField("user_id")
private Integer userId;
@TableField("name")
private String name;
}
2、创建Project类对应的mapper,这里记住,我们可以不用Service层,但是不能没有mapper层。
package com.mj.mybatisplus.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.mj.mybatisplus.po.Project;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface ProjectMapper extends BaseMapper<Project> {
}
3、创建一个VO类,表示查询返回的结果是一个user的集合,并且每个user都包含有它的多个Project对象集合。
package com.mj.mybatisplus.vo;
import com.mj.mybatisplus.po.Project;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
@Data
public class UserAndProjectVO {
@Schema(title = "userId",description = "主键id",defaultValue = "1")
private Integer id;
@Schema(description = "名称",defaultValue = "张飞",nullable = true,requiredMode = Schema.RequiredMode.REQUIRED)
private String username;
@Schema(title = "projects",description = "项目集合")
private List<Project> projects;
}
这是一种一对多关系,记得在hibernate里,经常用到一对多、多对多的注解,hibernate会默默地再生成一套表来记录这些关系映射,MyBatis-Plus里简化了这些,尽量不去修改数据库的元数据。
4、我们假设这个project表是一个不怎么常用的表,所以不需要为它建立Service层,所以我们在UserService里面添加一个方法,模拟进行user操作的时候用到project表。
//查询用户及其项目
List<UserAndProjectVO> queryUserAndProject(List<Integer> userIds);
5、在UserServiceImpl类中,添加一个方法,先查询user,再查询这些user对应的project,然后把这两部分数据合并起来。
@Override
public List<UserAndProjectVO> queryUserAndProject(List<Integer> userIds) {
List<User> users = listByIds(userIds);
//获取到真正查出来的用户id
List<Integer> ids = users.stream().map(User::getId).collect(Collectors.toList());
//使用Db类查出Project
List<Project> projects = Db.lambdaQuery(Project.class).in(Project::getUserId, ids).list();
//将查出来的Project对象集合按照userId整理成map
Map<Integer, List<Project>> projectMap = projects.stream().collect(Collectors.groupingBy(Project::getUserId));
//填充UserAndProjectVO对象
List<UserAndProjectVO> userAndProjectVOList = BeanUtil.copyToList(users, UserAndProjectVO.class);
for (UserAndProjectVO userAndProjectVO : userAndProjectVOList) {
userAndProjectVO.setProjects(projectMap.get(userAndProjectVO.getId()));
}
return userAndProjectVOList;
}
6、在UserController里添加一个测试接口。
@GetMapping("/queryUserAndProject")
@Operation(summary = "查询用户和项目", description = "查询用户和项目")
public ResponseEntity<List<UserAndProjectVO>> queryUserAndProject(@RequestParam List<Integer> ids) {
return ResponseEntity.ok(userService.queryUserAndProject(ids));
}