MybatisPlus实现高效的多对多查询

1、前置

事先声明一下代码中蕴含了大量的Stream和Lambda表达式操作,还不清楚的小伙伴可以去参考一下Java8新特性Stream流 ,而却我是用的是MybatisPlus这方面不清楚的也可以参考一下MybatisPlus基础用法;中间的对象转换除了使用Spring的BeanProperties外还使用了Mapstruct,关于MapStruct可以参考MapStruct使用

2、测试前准备

创建几张表用于做演示

DROP TABLE IF EXISTS `tb_dept`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `tb_dept` (
  `dept_id` bigint(20) NOT NULL COMMENT '主键ID(全局唯一)',
  `dept_name` varchar(30) DEFAULT NULL COMMENT '部门名称',
  `staff` int(11) DEFAULT NULL COMMENT '员工',
  `tel` varchar(50) DEFAULT NULL COMMENT '联系电话',
  `deleted` bit(1) DEFAULT b'0' COMMENT '逻辑删除(0:未删除;1:已删除)',
  `version` int(11) DEFAULT '0' COMMENT '乐观锁',
  `gmt_create` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `gmt_modified` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
  PRIMARY KEY (`dept_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='部门';
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `tb_dept`
--

LOCK TABLES `tb_dept` WRITE;
/*!40000 ALTER TABLE `tb_dept` DISABLE KEYS */;
INSERT INTO `tb_dept` (`dept_id`, `dept_name`, `staff`, `tel`, `deleted`, `version`, `gmt_create`, `gmt_modified`) VALUES (10,'1665646580778',20,'88886666',_binary '\0',4,'2020-10-30 11:48:19','2022-10-13 15:36:20'),(11,'Mysql',12,'80802121',_binary '\0',0,'2020-10-30 11:48:44','2021-05-24 15:11:20'),(12,'Tomcat',12,'23231212',_binary '\0',0,'2020-10-30 11:48:44','2021-05-24 15:11:23'),(13,'Nginx',13,'7116201',_binary '\0',0,'2020-10-30 11:48:45','2021-05-24 15:11:26');
/*!40000 ALTER TABLE `tb_dept` ENABLE KEYS */;
UNLOCK TABLES;

--
-- Table structure for table `tb_stu_sub_relation`
--

DROP TABLE IF EXISTS `tb_stu_sub_relation`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `tb_stu_sub_relation` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `stu_id` int(11) DEFAULT NULL COMMENT '学号ID',
  `sub_id` int(11) DEFAULT NULL COMMENT '学生ID',
  `score` int(11) DEFAULT NULL COMMENT '分数',
  PRIMARY KEY (`id`),
  KEY `stu_id` (`stu_id`),
  KEY `sub_id` (`sub_id`),
  CONSTRAINT `tb_stu_sub_relation_ibfk_1` FOREIGN KEY (`stu_id`) REFERENCES `tb_student` (`stu_id`),
  CONSTRAINT `tb_stu_sub_relation_ibfk_2` FOREIGN KEY (`sub_id`) REFERENCES `tb_subject` (`sub_id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8 COMMENT='学生与课程关系表';
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `tb_stu_sub_relation`
--

LOCK TABLES `tb_stu_sub_relation` WRITE;
/*!40000 ALTER TABLE `tb_stu_sub_relation` DISABLE KEYS */;
INSERT INTO `tb_stu_sub_relation` (`id`, `stu_id`, `sub_id`, `score`) VALUES (1,1,1,88),(2,1,2,67),(3,2,1,82);
/*!40000 ALTER TABLE `tb_stu_sub_relation` ENABLE KEYS */;
UNLOCK TABLES;

--
-- Table structure for table `tb_student`
--

DROP TABLE IF EXISTS `tb_student`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `tb_student` (
  `stu_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '学号ID',
  `stu_name` varchar(30) DEFAULT NULL COMMENT '姓名',
  PRIMARY KEY (`stu_id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COMMENT='学生表';
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `tb_student`
--

LOCK TABLES `tb_student` WRITE;
/*!40000 ALTER TABLE `tb_student` DISABLE KEYS */;
INSERT INTO `tb_student` (`stu_id`, `stu_name`) VALUES (1,'张三'),(2,'李四'),(3,'王五');
/*!40000 ALTER TABLE `tb_student` ENABLE KEYS */;
UNLOCK TABLES;

--
-- Table structure for table `tb_subject`
--

DROP TABLE IF EXISTS `tb_subject`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `tb_subject` (
  `sub_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '课程ID',
  `sub_name` varchar(30) DEFAULT NULL COMMENT '课程名',
  PRIMARY KEY (`sub_id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 COMMENT='课程表';
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `tb_subject`
--

LOCK TABLES `tb_subject` WRITE;
/*!40000 ALTER TABLE `tb_subject` DISABLE KEYS */;
INSERT INTO `tb_subject` (`sub_id`, `sub_name`) VALUES (1,'英语'),(2,'数学'),(3,'计算机'),(4,'操作系统'),(5,'数据库');
/*!40000 ALTER TABLE `tb_subject` ENABLE KEYS */;
UNLOCK TABLES;

--
-- Table structure for table `tb_user`
--

DROP TABLE IF EXISTS `tb_user`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `tb_user` (
  `user_id` bigint(20) NOT NULL COMMENT '主键ID(全局唯一)',
  `user_name` varchar(30) DEFAULT NULL COMMENT '姓名',
  `age` int(11) DEFAULT NULL COMMENT '年龄',
  `email` varchar(50) DEFAULT NULL COMMENT '邮箱',
  `dept_id` bigint(20) DEFAULT NULL COMMENT '部门ID',
  `deleted` bit(1) DEFAULT b'0' COMMENT '逻辑删除(0:未删除;1:已删除)',
  `version` int(11) DEFAULT '0' COMMENT '乐观锁',
  `gmt_create` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `gmt_modified` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
  PRIMARY KEY (`user_id`),
  KEY `dept_id` (`dept_id`),
  CONSTRAINT `tb_user_ibfk_1` FOREIGN KEY (`dept_id`) REFERENCES `tb_dept` (`dept_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='书籍';
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `tb_user`
--

LOCK TABLES `tb_user` WRITE;
/*!40000 ALTER TABLE `tb_user` DISABLE KEYS */;
INSERT INTO `tb_user` (`user_id`, `user_name`, `age`, `email`, `dept_id`, `deleted`, `version`, `gmt_create`, `gmt_modified`) VALUES (1,'1665646693248',1,'ab@c.c',10,_binary '\0',0,NULL,'2022-10-13 15:38:13'),(2,'Jack',3,'test2@baomidou.com',11,_binary '\0',0,NULL,'2021-05-24 15:12:04'),(3,'Billie',2,'test5@baomidou.com',12,_binary '\0',0,NULL,'2021-10-21 10:51:24'),(4,'didi',12,'test@qq.com',12,_binary '\0',0,'2021-06-05 19:22:46','2021-10-21 14:38:26');
/*!40000 ALTER TABLE `tb_user` ENABLE KEYS */;
UNLOCK TABLES;

3、我的依赖

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.qbb</groupId>
    <artifactId>MybatisPlusDemo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-parent</artifactId>
        <version>2.7.3</version>
        <relativePath/>
    </parent>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.2</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>


        <!--swagger-->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-boot-starter</artifactId>
            <version>3.0.0</version>
        </dependency>
        <!--swagger-ui-->
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-spring-boot-starter</artifactId>
            <version>3.0.3</version>
        </dependency>

        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct</artifactId>
            <version>1.5.3.Final</version>
        </dependency>

        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct-processor</artifactId>
            <version>1.5.3.Final</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.10</version>
        </dependency>
    </dependencies>
</project>

4、单表查询

单表查询MybaitsPlus已经做的很好了,我就不重复了

@Operation(summary = "单表查询-----用户列表")
    @GetMapping("/list")
    public Q list(User user) {
        return Q.success(userService.list(Wrappers.query(user)));
    }

    @Operation(summary = "单表查询-----用户列表page")
    @GetMapping("/page")
    public Q page(PageEntity pageEntity, User user) {
        return Q.success(userService.page(pageEntity.toPage(), Wrappers.lambdaQuery(user)));
    }

    @Operation(summary = "单表查询-----新增")
    @PostMapping("/add")
    public Q add(@RequestBody User user) {
        return Q.success(userService.save(user));
    }

    @Operation(summary = "单表查询-----修改")
    @PutMapping("/edit")
    public Q edit(@RequestBody User user) {
        return Q.success(userService.updateById(user));
    }

    @Operation(summary = "单表查询-----批量删除")
    @DeleteMapping("/batchRemove")
    public Q batchRemove(@Parameter(name = "ids", description = "用户ID列表") @RequestBody Long[] ids) {
        return Q.success(userService.removeBatchByIds(Arrays.asList(ids)));
    }

    @Operation(summary = "单表查询-----根据ID查询")
    @GetMapping("/detail/{id}")
    public Q detail(@Parameter(name = "id", description = "用户ID") @PathVariable("id") Long id) {
        return Q.success(userService.getById(id));
    }

5、一对一查询

/*===========================一对一查询START===============================*/
    @Override
    public UserVO voDetail(Long id) {
        // 查询用户信息
        User user = this.getById(id);
        // 转换为vo对象
        UserVO userVO = Optional.ofNullable(user).map(UserVO::new).orElse(null);
        // 组装数据
        Optional.ofNullable(userVO).ifPresent(this::addDeptNameInfo);
        return userVO;
    }

    private void addDeptNameInfo(UserVO userVO) {
        Dept dept = deptService.getOne(Wrappers.<Dept>lambdaQuery().eq(Dept::getDeptId, userVO.getDeptId()));
        Optional.ofNullable(dept).ifPresent(d -> userVO.setDeptName(d.getDeptName()));
    }

    @Override
    public IPage<UserVO> voPage(PageEntity page, User user) {
        // 先根据条件查询用户列表
        IPage<User> userPage = this.page(page.toPage(), Wrappers.lambdaQuery(user));
        // 初始化Vo
        IPage<UserVO> userVoPage = userPage.convert(UserVO::new);
        if (userVoPage.getRecords().size() > 0) {
            addDeptNameInfo(userVoPage);
        }
        return userVoPage;
    }

    private void addDeptNameInfo(IPage<UserVO> userVoPage) {
        // 提取用户userId,方便批量查询
        Set<Long> deptIds = userVoPage.getRecords().stream().map(User::getDeptId).collect(toSet());
        // 根据deptId查询deptName
        List<Dept> dept = deptService.list(Wrappers.lambdaQuery(Dept.class).in(Dept::getDeptId, deptIds));
        // 构造映射关系,方便匹配deptId与deptName
        Map<Long, String> hashMap = dept.stream().collect(toMap(Dept::getDeptId, Dept::getDeptName));
        // 将查询补充的信息添加到Vo中
        userVoPage.convert(e -> {
            e.setDeptName(hashMap.get(e.getDeptId()));
            return e;
        });
    }

    @Override
    public List<UserVO> voList(User user) {
        List<User> userList = this.list(Wrappers.lambdaQuery(user));
        List<UserVO> userVOList = userList.stream().map(UserVO::new).collect(Collectors.toList());
        // 此步骤可以有多个
        addDeptNameInfo(userVOList);
        return userVOList;
    }

    private void addDeptNameInfo(List<UserVO> userVOList) {
        // 提取userVOList中的deptId集合
        Set<Long> deptIds = userVOList.stream().map(UserVO::getDeptId).collect(toSet());
        // 根据in(id1,id2,id3...)查询
        List<Dept> depts = deptService.list(Wrappers.<Dept>lambdaQuery().select(Dept::getDeptId, Dept::getDeptName).in(Dept::getDeptId, deptIds));
        // 构造映射关系,方便匹配deptId与deptName
        Map<Long, String> hashMap = depts.stream().collect(toMap(Dept::getDeptId, Dept::getDeptName));
        // 封装Vo,并添加到集合中(关键内容)
        userVOList.forEach(e -> e.setDeptName(hashMap.get(e.getDeptId())));
    }

    // =====================================   easy写法   =========================================

    @Override
    public UserVO voDetailEasy(Long id) {
        UserVO userVO = EntityUtils.toObj(this.getById(id), UserVO::new);
        Dept dept = deptService.getById(userVO.getDeptId());
        return CONVERT.appendAttrToUserVO(dept, userVO);
    }

    @Override
    public IPage<UserVO> voPageEasy(PageEntity page, User user) {
        IPage<UserVO> toPage = EntityUtils.toPage(page(page.toPage(User.class), Wrappers.lambdaQuery(user)), UserVO::new);
        Set<Long> deptIds = EntityUtils.toSet(toPage.getRecords(), UserVO::getDeptId);
        Map<Long, Dept> deptMap = EntityUtils.toMap(deptService.listByIds(deptIds), Dept::getDeptId, e -> e);
        toPage.convert(e -> CONVERT.appendAttrToUserVO(deptMap.get(e.getDeptId()), e));
        return toPage;
    }

    @Override
    public List<UserVO> voListEasy(User user) {
        List<UserVO> userVOList = EntityUtils.toList(list(Wrappers.lambdaQuery(user)), UserVO::new);
        Set<Long> deptIds = EntityUtils.toSet(userVOList, UserVO::getDeptId);
        Map<Long, Dept> deptMap = EntityUtils.toMap(deptService.listByIds(deptIds), Dept::getDeptId, e -> e);
        userVOList = userVOList.parallelStream().map(e -> CONVERT.appendAttrToUserVO(deptMap.get(e.getDeptId()), e)).collect(Collectors.toList());
        return userVOList;
    }

    /*===========================一对一查询END===============================*/

6、一对多查询

/**
     * 单个对象:一个部门对应多个用户
     *
     * @param id
     * @return
     */
    @Override
    public DeptVO voDetailEasyOneToMany(Long id) {
        // 先查询部门信息
        Dept dept = this.getById(id);
        // 把部门信息转换成deptVO
        DeptVO deptVO = Optional.ofNullable(dept).map(CONVERT::deptToDeptVO).orElse(null);
        // 填充部门的员工信息
        Optional.ofNullable(deptVO).ifPresent(this::addUserInfo);
        return deptVO;
    }

    private void addUserInfo(DeptVO deptVO) {
        // 根据部门ID查询用户信息
        List<User> userList = userService.list(Wrappers.lambdaQuery(User.class).eq(User::getDeptId, deptVO.getDeptId()));
        Optional.ofNullable(userList).ifPresent(deptVO::setUserList);
    }


    /**
     * 分页查询:一个部门对应多个用户
     *
     * @param page
     * @param dept
     * @return
     */
    @Override
    public IPage<DeptVO> voPageEasyOneToMany(PageEntity page, Dept dept) {
        IPage<DeptVO> toPage = EntityUtils.toPage(page(page.toPage(Dept.class), Wrappers.lambdaQuery(dept)), DeptVO::new);
        if (toPage.getRecords().size() > 0) {
            addUserInfo(toPage);
        }
        return toPage;
    }

    private void addUserInfo(IPage<DeptVO> toPage) {
        // 查询部门对应的多个员工
        Set<Long> deptIds = EntityUtils.toSet(toPage.getRecords(), DeptVO::getDeptId);
        // 用批量deptId查询用户信息
        List<User> userList = userService.list(Wrappers.lambdaQuery(User.class).in(User::getDeptId, deptIds));
        // 使用stream流对用户信息进行分组 Map<deptId,用户列表>,方便后面根据deptId直接获取用户列表信息
        Map<Long, List<User>> listMap = userList.parallelStream().collect(Collectors.groupingBy(User::getDeptId));
        // 方式一:
        // toPage.getRecords().forEach(e -> e.setUserList(listMap.get(e.getDeptId())));
        // 方式二:
        toPage.convert(deptVO -> {
            deptVO.setUserList(listMap.get(deptVO.getDeptId()));
            return deptVO;
        });
    }

    /**
     * 列表查询:一个部门对应多个用户
     *
     * @param dept
     * @return
     */
    @Override
    public List<DeptVO> voListEasyOneToMany(Dept dept) {
        // 查询出部门列表
        List<DeptVO> toList = EntityUtils.toList(list(Wrappers.lambdaQuery(dept)), DeptVO::new);
        Set<Long> deptIds = EntityUtils.toSet(toList, DeptVO::getDeptId);
        List<User> userList = userService.list(Wrappers.lambdaQuery(User.class).in(User::getDeptId, deptIds));
        Map<Long, List<User>> listMap = userList.parallelStream().collect(Collectors.groupingBy(User::getDeptId));
        toList.forEach(e -> e.setUserList(listMap.get(e.getDeptId())));
        return toList;
    }

7、多对多查询

// =======================================================根据学生信息查询对应课程信息 START=======================================================

    /**
     * 根据学生ID查询学生信息,并且查询此学生的课程信息
     *
     * @param id
     * @return
     */
    @Override
    public StudentVO voDetailEasyStuManyToSubMany(Long id) {
        // 先查询学生信息
        Student student = studentService.getById(id);
        // 把学生信息转换成学生BO
        StudentVO studentVO = EntityUtils.toObj(student, StudentVO::new);
        // 查询匹配的关系
        List<StuSubRelation> stuSubRelationList = this.list(Wrappers.<StuSubRelation>lambdaQuery().eq(StuSubRelation::getStuId, id));
        // 获取课程ID列表
        Set<Long> subIds = EntityUtils.toSet(stuSubRelationList, StuSubRelation::getSubId);
        if (Objects.nonNull(studentVO) && !subIds.isEmpty()) {
            // 根据课程ID列表查询课程信息
            List<Subject> subjectList = subjectService.list(Wrappers.<Subject>lambdaQuery().in(Subject::getSubId, subIds));
            // domain ---> BO
            List<SubjectBO> subjectBOList = SubjectConvert.CONVERT.subListToSubBOList(subjectList);
            // 转换为table对象  table对象可以理解为是一个双键Map  ===>  Map<rowKey,Map<columnKey,value>>
            // Table<Long, Long, StuSubRelation> table = TableUtils.createHashTable(stuSubRelationList, StuSubRelation::getStuId, StuSubRelation::getSubId);
            subjectBOList.forEach(StuSubRelationConvert.CONVERT::stuSubRelationToSubjectBO);
            studentVO.setSubjectBOList(subjectBOList);
        }
        return studentVO;
    }

    /**
     * 根据查询条件查询学生信息列表,并且查询出对应学生的课程信息
     *
     * @param student 查询条件
     * @return
     */
    @Override
    public List<StudentVO> voListEasyStuManyToSubMany(Student student) {
        // 根据条件查询学生信息列表
        List<Student> studentList = studentService.list(Wrappers.lambdaQuery(student));
        // student ---> studentVO
        List<StudentVO> studentVOList = EntityUtils.toList(studentList, StudentVO::new);
        // 提取studentIds
        Set<Long> studentIds = EntityUtils.toSet(studentVOList, Student::getStuId);
        if (studentIds.size() == 0) {
            return studentVOList;
        }
        // 根据studentIds去中间表中查询对应关系列表
        List<StuSubRelation> stuSubRelations = list(Wrappers.<StuSubRelation>lambdaQuery().in(StuSubRelation::getStuId, studentIds));
        // 提取subjectIds
        Set<Long> subjectIds = EntityUtils.toSet(stuSubRelations, StuSubRelation::getSubId);
        if (subjectIds.size() == 0) {
            return studentVOList;
        }
        /**
         * 分组转换:
         *     源数据:
         *          1 - 1
         *          1 - 2
         *          2 - 1
         *          2 - 3
         *     转换后:
         *          1 - [1,2]
         *          2 - [1,3]
         */
        Map<Long, List<Long>> map = stuSubRelations.stream().collect(Collectors.groupingBy(StuSubRelation::getStuId,
                Collectors.mapping(StuSubRelation::getSubId, Collectors.toList())));
        // 转换为table对象  table对象可以理解为是一个双键Map  ===>  Map<rowKey,Map<columnKey,value>> 详细的使用参考:https://www.cnblogs.com/qbbit/p/16965597.html
        // Table<Long, Long, StuSubRelation> table = TableUtils.createHashTable(stuSubRelations, StuSubRelation::getStuId, StuSubRelation::getSubId);
        // 根据subjectIds查询课程信息列表
        List<Subject> subjectList = subjectService.list(Wrappers.<Subject>lambdaQuery().in(Subject::getSubId, subjectIds));
        // 使用MapStruct进行高效数据转换
        List<SubjectBO> subjectBOList = SubjectConvert.CONVERT.subListToSubBOList(subjectList);
        // 设置课程信息
        studentVOList.forEach(studentAction(map, subjectBOList));
        return studentVOList;
    }

    /**
     * 根据查询条件查询学生信息分页列表,并且查询出对应学生的课程信息
     *
     * @param page    分页信息
     * @param student 查询条件
     * @return
     */
    @Override
    public IPage<StudentVO> voPageEasyStuManyToSubMany(IPage<Student> page, Student student) {
        IPage<Student> studentIPage = studentService.page(page, Wrappers.lambdaQuery(student));
        IPage<StudentVO> studentVOPage = EntityUtils.toPage(studentIPage, StudentVO::new);
        Set<Long> studentIds = EntityUtils.toSet(studentVOPage.getRecords(), Student::getStuId);
        if (studentIds.size() == 0) {
            return studentVOPage;
        }
        List<StuSubRelation> stuSubRelations = list(Wrappers.lambdaQuery(StuSubRelation.class).in(StuSubRelation::getStuId, studentIds));
        Set<Long> subjectIds = EntityUtils.toSet(stuSubRelations, StuSubRelation::getSubId);
        if (subjectIds.size() == 0) {
            return studentVOPage;
        }
        Map<Long, List<Long>> map = stuSubRelations.stream().collect(Collectors.groupingBy(StuSubRelation::getStuId, Collectors.mapping(StuSubRelation::getSubId, Collectors.toList())));
        List<Subject> subjectList = subjectService.list(Wrappers.lambdaQuery(Subject.class).in(Subject::getSubId, subjectIds));
        List<SubjectBO> subjectBOList = SubjectConvert.CONVERT.subListToSubBOList(subjectList);
        studentVOPage.getRecords().forEach(studentAction(map, subjectBOList));
        return studentVOPage;
    }

    @NotNull
    private static Consumer<StudentVO> studentAction(Map<Long, List<Long>> map, List<SubjectBO> subjectBOList) {
        return studentVO -> {
            List<SubjectBO> list = subjectBOList.stream().filter(e -> map.get(studentVO.getStuId()) != null && map.get(studentVO.getStuId()).contains(e.getSubId())).collect(Collectors.toList());
            list.forEach(StuSubRelationConvert.CONVERT::stuSubRelationToSubjectBO);
            studentVO.setSubjectBOList(list);
        };
    }

    // =======================================================根据学生信息查询对应课程信息 END=======================================================

    // =======================================================根据课程信息查询对应学生信息 START=======================================================

    /**
     * 根据课程ID查询课程信息,并且查询此课程的学生信息
     *
     * @param id 课程ID
     * @return 一条记录
     */
    @Override
    public SubjectVO voDetailEasySubManyToStuMany(Long id) {
        // 根据课程ID查询课程信息
        Subject subject = subjectService.getById(id);
        // 将subject转换为subjectVO
        SubjectVO subjectVO = EntityUtils.toObj(subject, SubjectVO::new);
        // 查询匹配关系
        List<StuSubRelation> stuSubRelationList = this.list(Wrappers.<StuSubRelation>lambdaQuery().eq(StuSubRelation::getSubId, id));
        // 获取学生ID列表
        Set<Long> stuIds = EntityUtils.toSet(stuSubRelationList, StuSubRelation::getStuId);
        if (Objects.nonNull(subjectVO) && stuIds.size() > 0) {
            // 根据学生ID列表查询学生信息
            List<Student> studentList = studentService.list(Wrappers.<Student>lambdaQuery().in(Student::getStuId, stuIds));
            // domain ---> BO
            List<StudentBO> studentBOList = StudentConvert.CONVERT.stuListToStuBOList(studentList);
            studentBOList.forEach(StuSubRelationConvert.CONVERT::stuSubRelationToStudentBO);
            subjectVO.setStudentBOList(studentBOList);
        }
        return subjectVO;
    }

    /**
     * 根据查询条件查询学生信息列表,并且查询出对应学生的课程信息
     *
     * @param subject 查询条件
     * @return
     */
    @Override
    public List<SubjectVO> voListEasySubManyToStuMany(Subject subject) {
        // 根据条件查询课程列表
        List<Subject> subjectList = subjectService.list(Wrappers.lambdaQuery(subject));
        // subject ---> subjectVO
        List<SubjectVO> subjectVOList = EntityUtils.toList(subjectList, SubjectVO::new);
        // 提取subjectIds
        Set<Long> subjectIds = EntityUtils.toSet(subjectVOList, Subject::getSubId);
        if (subjectIds.size() == 0) {
            return subjectVOList;
        }
        // 提取subjectIds去中间表查询对应关系列表
        List<StuSubRelation> stuSubRelationList = list(Wrappers.<StuSubRelation>lambdaQuery().in(StuSubRelation::getSubId, subjectIds));
        // 提取studentIds
        Set<Long> studentIds = EntityUtils.toSet(stuSubRelationList, StuSubRelation::getStuId);
        if (studentIds.size() == 0) {
            return subjectVOList;
        }
        Map<Long, List<Long>> map = stuSubRelationList.stream()
                .collect(Collectors.groupingBy(StuSubRelation::getStuId, Collectors.mapping(StuSubRelation::getSubId, Collectors.toList())));
        List<Student> studentList = studentService.list(Wrappers.<Student>lambdaQuery().in(Student::getStuId, studentIds));
        List<StudentBO> studentBOList = StudentConvert.CONVERT.stuListToStuBOList(studentList);
        subjectVOList.forEach(subjectAction(map, studentBOList));
        return subjectVOList;
    }

    /**
     * 根据查询条件查询学生信息分页列表,并且查询出对应学生的课程信息
     *
     * @param page    分页信息
     * @param subject 查询条件
     * @return
     */
    @Override
    public IPage<SubjectVO> voPageEasySubManyToStuMany(Page<Subject> page, Subject subject) {
        IPage<SubjectVO> subjectVOPage = EntityUtils.toPage(subjectService.page(page, Wrappers.lambdaQuery(subject)), SubjectVO::new);
        Set<Long> subjectIds = EntityUtils.toSet(subjectVOPage.getRecords(), Subject::getSubId);
        if (subjectIds.size() == 0) {
            return subjectVOPage;
        }
        List<StuSubRelation> stuSubRelations = list(Wrappers.lambdaQuery(StuSubRelation.class).in(StuSubRelation::getSubId, subjectIds));
        Set<Long> studentIds = EntityUtils.toSet(stuSubRelations, StuSubRelation::getStuId);
        if (studentIds.size() == 0) {
            return subjectVOPage;
        }
        Map<Long, List<Long>> map = stuSubRelations.stream()
                .collect(Collectors.groupingBy(StuSubRelation::getSubId, Collectors.mapping(StuSubRelation::getStuId, Collectors.toList())));
        List<Student> studentList = studentService.list(Wrappers.lambdaQuery(Student.class).in(Student::getStuId, studentIds));
        List<StudentBO> studentBOList = StudentConvert.CONVERT.stuListToStuBOList(studentList);
        subjectVOPage.getRecords().forEach(subjectAction(map, studentBOList));
        return subjectVOPage;
    }

    @NotNull
    private static Consumer<SubjectVO> subjectAction(Map<Long, List<Long>> map, List<StudentBO> studentBOList) {
        return (subjectVO) -> {
            List<StudentBO> list = studentBOList.stream()
                    .filter(e -> map.get(subjectVO.getSubId()) != null && map.get(subjectVO.getSubId()).contains(e.getStuId())).collect(Collectors.toList());
            list.forEach(StuSubRelationConvert.CONVERT::stuSubRelationToStudentBO);
            subjectVO.setStudentBOList(list);
        };
    }
    // =======================================================根据学生信息查询对应课程信息 END=======================================================

代码仓库

更多的大家可以参考这位大佬的博客,我是在这位大佬的基础上做了一些自定义~ 赛先生和泰先生

  • 1
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值