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=======================================================

代码仓库

MybatisPlus实现高效的多对多查询的更多相关文章

  1. 22Mybatis_订单商品数据模型_多对多查询以及对多对多查询的总结

    之前讲了一对一,一对多查询,这篇文章讲的是多对多. 先给出需求:查询用户及用户购买商品信息. 我们由之前的文章知道,这个需求是多对多的. 还是那个终止我们的mybatis所做的不管是之前的一对一还是一 ...

  2. mybatis(一、原理,一对多,多对一查询)

    MyBatis框架及原理分析 MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架,其主要就完成2件事情: 封装JDBC操作 利用反射打通Java类与SQL语句之间的相互转换 ...

  3. flask的orm框架(SQLAlchemy)-一对多查询以及多对多查询

    一对多,多对多是什么? 一对多.例如,班级与学生,一个班级对应多个学生,或者多个学生对应一个班级. 多对多.例如,学生与课程,可以有多个学生修同一门课,同时,一门课也有很多学生. 一对多查询 如果一个 ...

  4. SpringBoot使用Mybatis注解进行一对多和多对多查询(2)

    SpringBoot使用Mybatis注解进行一对多和多对多查询 GitHub的完整示例项目地址kingboy-springboot-data 一.模拟的业务查询 系统中的用户user都有唯一对应的地 ...

  5. MyBatis多对多查询

    -------------------siwuxie095                                 MyBatis 多对多查询         以订单和商品为例,即 一个订单可 ...

  6. mybatis由浅入深day02_4多对多查询_多对多查询总结

    4 多对多查询 4.1 需求(查询用户及用户购买商品信息) 查询用户及用户购买商品信息. 4.2 sql语句 查询主表是:用户表 关联表:由于用户和商品没有直接关联,通过订单和订单明细进行关联,所以关 ...

  7. 基于对象的跨表查询,多对多查询,多对多操作,聚合查询和分组查询,F查询和Q 查询

    基于对象的跨表查询 一对多查询(班级表和学生表) 表结构创建 class Class(models.Model): id = models.AutoField(primary_key=True) cn ...

  8. mybatis学习记录六——一对一、一对多和多对多查询

    9       订单商品数据模型 9.1     数据模型分析思路 1.每张表记录的数据内容 分模块对每张表记录的内容进行熟悉,相当 于你学习系统 需求(功能)的过程. 2.每张表重要的字段设置 非空 ...

  9. 数据库开发-Django ORM的多对多查询

    数据库开发-Django ORM的多对多查询 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.联合主键问题 CREATE TABLE `employees` ( `emp_no` ...

  10. day03-Mybatis中一对一、一对多、多对多查询

    一对一查询 一对一的表结构: my_account表: my_user表: 一对一是互相的,A可以找到B,B也可以找到A,方法是一样的,这里就只写一个方向的 通过my_count表找到my_user表 ...

随机推荐

  1. Midjourney的一些学习心得:如何高效的图生图

    注意本文没有什么长篇大论,全部是自己的学习心得. 心得体会:如何图生图 今天在一篇midjourney看到好图应该怎么抄. 相信经常会看到好图也想要的,但是要么抄不出感觉,要么抄过来把水印也抄了,这一 ...

  2. 企业级低代码平台,通用代码生成平台,Java开源项目(附源码)

    项目介绍 Jeecg-Boot 是一款基于代码生成器的智能开发平台!采用前后端分离架构:SpringBoot,Mybatis,Shiro,JWT,Vue&Ant Design.强大的代码生成器 ...

  3. signalr断开连接后重新连接

    signalr断开连接后重新连接 产品需求连接signalr 不稳定,连着连着就断了,场面十分尴尬,导致产品经理现场被批!!(内心无比高兴 ) 分析得出问题现象: 服务器因某些特殊原因,导致服务停止一 ...

  4. C#应用程序的多语言方案 - 开源研究系列文章

    今天讲讲笔者自创的C#应用程序多语言的方案. 这个多语言方案,主要是对应用的窗体及其控件进行检索,然后根据控件的名称进行在语言字典里进行检索获取到对应的语言文本进行赋值显示的.笔者对网上的多语言方案进 ...

  5. 杰哥教你面试之一百问系列:java集合

    目录 1. 什么是Java集合?请简要介绍一下集合框架. 2. Java集合框架主要分为哪几种类型? 3. 什么是迭代器(Iterator)?它的作用是什么? 4. ArrayList和LinkedL ...

  6. 使用 Python ssh 远程登陆服务器的最佳方案

    在使用 Python 写一些脚本的时候,在某些情况下,我们需要频繁登陆远程服务去执行一次命令,并返回一些结果. 在 shell 环境中,我们是这样子做的. sshpass -p ${passwd} s ...

  7. 快速搭建SpringBoot3.x项目

    写在前面 上一小节中我们从0到1 使用Vite搭建了一个Vue3项目,并集成了Element Plus 实现了一个简单的增删改查页面. 这一篇中我们将使用IDEA快速搭建一个SpringBoot3.x ...

  8. 实用工具、01 效率篇 | 几个操作快速提升 Typora 使用体验

    本篇文章旨在提高大家记笔记的效率,分享的工具请按个人需求安装 Typora-plugins 为 Typora 添加更多新功能,我最喜欢的是多标签页管理 obgnail/typora_plugin: T ...

  9. 前端设计模式:单例模式(Singleton)

    00.基本概念 单例模式(Singleton Pattern),也称单体模式,就是全局(或某一作用域范围)唯一实例,大家共享.复用一个实例对象,也可减少内存开销.单例模式应该是最基础.也最常见的设计模 ...

  10. 在 Net7.0环境下测试了 Assembly.Load、Assmebly.LoadFile和Assembly.LoadFrom的区别

    一.简介 很长时间没有关注一些C#技术细节了,主要在研究微服务.容器.云原生.编批等高大上的主题了,最近在写一些框架的时候,遇到了一些和在 Net Framework 框架下不一样的情况,当然了,我今 ...