@JFinal 你好,想跟你请教个问题:
我在使用jfinal返回到客户端json数据的时候,想如何避免N+1次查询。
比如显示一个帖子列表的时候,需要返回给客户端 { [ { "blog_id":1,"title","xxxx","user":{}},{ "blog_id":1,"title","xxxx","user":{}}]}
如果用 blog left join user,那么生成json的时候,得用Map重新构造一下查找出来的List<Record>
如果不用left join, 那就是得先查找出List<Blog>,然后遍历的时候,再发一条sql,用blog.put("user",user);来实现,
用哪种方案好呢?场景是移动服务端。
或者有别的方案更合适,那也很好。
直接 sql 解决即可:
由于每个 Blog 必定与一个 User 关联,所以无所谓 left join 和 inner join 了,必定会关联得上。注意上面的 select 块中示范了最可能用到的 u.id、u.name,这里按需求来做。
这个方案对于多个 blog 对应同一个 user 会有一定的数据冗余,但如果 user 表中需要的数据很少,例如只有 id和name的话可以忽略其影响,如果冗余非常之大,可以采用下面的方式:
1: sql 查出需要的 blogList
2:从 blogList 得到所对应的用户 id 集合,然后通过 select ... from user where id in(id集合)得到 blogList 所对应的 userList
3:对 blogList 进行循环,将 userList 中相对应的数据使用 blog.put("user", user) 放进去
3:renderJson(blogList);
这个方案只需要执行两条 sql,而不是 N + 1 条 sql。这个方案还可以让上面的第三步在客户端进行,而服务端只需要将 blogList、userList 的 json 数据同时发过去即可。
注意确认下select ... from user where id in(id集合)得到 blogList 所对应的 userList ,
这里的userList会不会跟blogList按 i 的顺序一一对应,要不然那就得进行 N*N轮判断去匹配了。而不是N轮设值
额,实验了下。
在 findblogsOfUser(uid)情况下, 先查user,再查 blogs, 再user.put("blogs",blogs). 2次sql.在 findBlogById(blogid)下,用map重构效率更高。