- 1.使用场景
- 2.菜鸟(我)的写法
- 3.更看好的写法
- 4.优缺点
不多bb直接上问题:
这里有两张表,表关系一对多,开发中常见的需求:
先分页查询出user表下的n条数据,再关联查询出note表中与之关联的数据
比如:分页查询 每页10条用户(user)数据,返回结果需要携带每个用户发表的笔记(note)
这段代码只需要关注中间的查询过程
1.先进行分页查询,拿到全部的10条(user)数据。
2.使用循环查询每一条User下的全部note数据
3.组装数据返回
问题:只看结果的话,这样写好像也没啥毛病,可以拿到想要的数据,但是!!!我们来看一下我们查询了几次数据库 如果我没数错 11次!!! 这是每页10条数据,如果每页20条或者50条数据呢?
刚开始遇到类似的需求,我也都是使用上面的方式,刚开始学的时候我也想过有没有更好的方法呢?我还看了其他人写的代码,好像都是这样写的 直到我学会了下面的这个方式
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
这段代码我们还是只关注查询数据的方式
1.先进行分页查询,拿到全部的10条(user)数据。(不变)
2.拿到10条数据的userId,使用关键词“in”查询我们需要的全部数据
3.使用Collectors.groupingBy分组
4.组装数据返回(拿到的数据完全一样)
问题:这段代码相对第一种方式有点点难度,不过认真看一下还是蛮简单的,我们先看一下这次我们查询了几次数据库 没数错的话 2次! 相对之前的方法查询数据库次数变少了 那么时间呢?请看
| 次数 | 第一种时间(ms) | 第二种时间(ms) |
|---|---|---|
| 1 | 23 | 6 |
| 2 | 21 | 5 |
| 3 | 19 | 7 |
| 4 | 20 | 6 |
| 5 | 21 | 6 |
以上数据使用 Postman 测试得到
4.优缺点对比上面的两种方法,代码量来看 第一种更简单,更容易理解;第二种代码相对更复杂。效率来看 第二种方法优于第一种,毕竟程序在内存中的计算比反复的查询数据库花费的时间更少,更快一点。
我也只是针对很少数据进行了测试 user表:10条 note表:50条
感兴趣的小伙伴可以尝试更多的数据,如果本篇博客有技术性错误,欢迎留言批评☻☻☻
下面给到重点的代码和素材表结构
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
代码块1:
@GetMapping("list1")
public R getUserList1(){
long time_start = new Date().getTime(); //开始时间
Page page = new Page<>(1, 10); //分页 查询10个
userService.page(page, null);
//查询出 UserList 进行遍历查询 Note
List userList = page.getRecords();
List collect = userList.stream().map(user -> {
Long userId = user.getId();
List list = noteService.list(new LambdaQueryWrapper().eq(NoteEntity::getUserId, userId));
UserRes userRes = new UserRes();
BeanUtils.copyProperties(user, userRes);
userRes.setNoteList(list);
return userRes;
}).collect(Collectors.toList());
long time_end = new Date().getTime(); //结束时间
//返回结果数据 完全一样
return R.ok().put("data",collect).put("atime",time_end-time_start);
}
代码块2
@GetMapping("list2")
public R getUserList2(){
long time_start = new Date().getTime(); //开始时间
Page page = new Page<>(1, 10); //分页
userService.page(page, null); //条件一致
//查询出 UserList 非遍历查询 使用'in'关键字一次查询出所有需要的数据
List userList = page.getRecords();
List userIdList = userList.stream().map(UserEntity::getId).collect(Collectors.toList());
List list = noteService.list(new LambdaQueryWrapper().in(NoteEntity::getUserId, userIdList));
//使用Collectors.groupingBy分组并组装数据
Map> NoteListMap = list.stream().collect(Collectors.groupingBy(NoteEntity::getUserId));
List collect = userList.stream().map(user -> {
UserRes userRes = new UserRes();
BeanUtils.copyProperties(user, userRes);
userRes.setNoteList(NoteListMap.get(user.getId()));
return userRes;
}).collect(Collectors.toList());
long time_end = new Date().getTime();
//返回结果数据 完全一样
return R.ok().put("data",collect).put("atime",time_end-time_start);
}
表结构(数据自造)
CREATE TABLE `notes_note` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键', `title` varchar(50) DEFAULT NULL COMMENT '标题', `user_id` bigint(20) DEFAULT NULL COMMENT '作者', `content` longtext COMMENT '内容', `type` tinyint(1) DEFAULT NULL COMMENT '类型 rn1.文本 rn2.视频(url) rn3.pdf(url) rn4.图片(url) rn5.音乐(url) rn6.html(url)', `lable` varchar(20) DEFAULT NULL COMMENT '内容分组/标签 ', `create_date` datetime DEFAULT NULL COMMENT '创建时间', `update_date` datetime DEFAULT NULL COMMENT '更新时间', `is_deleted` tinyint(1) DEFAULT '0' COMMENT '0可用 1不可用', PRIMARY KEY (`id`) USING BTREE ) ENGINE=InnoDB AUTO_INCREMENT=47 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC COMMENT='笔记表'; CREATE TABLE `notes_user` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键', `nick_name` varchar(20) DEFAULT NULL COMMENT '昵称', `user_name` varchar(20) NOT NULL COMMENT '用户名', `email` varchar(30) DEFAULT NULL COMMENT '邮箱地址', `password` varchar(30) DEFAULT NULL COMMENT '密码', `salt` varchar(30) DEFAULT NULL COMMENT '密码加密盐', `create_date` datetime DEFAULT NULL COMMENT '创建时间', `update_date` datetime DEFAULT NULL COMMENT '更新时间', `is_deleted` tinyint(1) DEFAULT '0' COMMENT '是否删除 0可用 1删除', PRIMARY KEY (`id`) USING BTREE, KEY `user_name` (`user_name`) USING BTREE COMMENT '账号 索引', KEY `email` (`email`) USING BTREE COMMENT '邮箱地址索引' ) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC COMMENT='用户表';
R、Res:
public class R extends HashMap{ private static final long serialVersionUID = 1L; public R() { put("code", 0); } public static R error() { return error(500, "未知异常,请联系管理员"); } public static R error(String msg) { return error(500, msg); } public static R error(int code, String msg) { R r = new R(); r.put("code", code); r.put("msg", msg); return r; } public static R ok(String msg) { R r = new R(); r.put("msg", msg); return r; } public static R ok(Map map) { R r = new R(); r.putAll(map); return r; } public static R ok() { return new R(); } public R put(String key, Object value) { super.put(key, value); return this; } } //----------------------------------------------------------------------------------// @Data @Accessors(chain = true) public class UserRes extends UserEntity { private List noteList; }
如果对Collectors.groupingBy用法不了解请看:
java8中的Collectors.groupingBy用法



