作者: 剽悍一小兔
CSDN前端优质创作者,打破编程小说次元壁第一人《JavaScript百炼成仙》作者,专注Java硬核干货分享,分享创造快乐,技术成就梦想!
我们在工作中,经常会因为一条慢sql调半天。这一节,我给大家介绍一种提升查询效率的思路,那就是让Java内存帮我们分担一些运算。
案例还是采用 springBoot日记本系统,源码下载地址和教程在文末。
先改一个BUG
之前遗留了一个BUG需要我们解决,就是在日记的详情页,日记类型没有做转换。
让我们看下controller:
@RequestMapping("diary/{id}.html")
@SaCheckLogin
public ModelAndView getDiary(@PathVariable Long id, ModelAndView mav){
TblSynBlog tblSynBlog = blogService.selectOne(id);
mav.addObject("blog",tblSynBlog);
mav.addObject("statistics",blogService.getBlogsStatistics());
mav.setViewName("detail");
return mav;
}
破案了,代码中直接把tblSynBlog放到了modelAndView中,没有对Type进行专门的处理。
现在开始改BUG:
思路很简单,根据日记的type去类型表查询具体的中文是啥,再返回就可以了。
@RequestMapping("diary/{id}.html")
@SaCheckLogin
public ModelAndView getDiary(@PathVariable Long id, ModelAndView mav){
TblSynBlog tblSynBlog = blogService.selectOne(id);
//对Type进行中文转义
SysBlogType type = sysBlogTypeService.getByTypeId(tblSynBlog.getBlogType());
mav.addObject("blogType",type.getTypeName());
mav.addObject("blog",tblSynBlog);
mav.addObject("statistics",blogService.getBlogsStatistics());
mav.setViewName("detail");
return mav;
}
ISysBlogTypeService
SysBlogType getByTypeId(String blogType);
SysBlogTypeServiceImpl
@Override
public SysBlogType getByTypeId(String blogType) {
return baseMapper.selectById(Integer.parseInt(blogType));
}
我们一般不推荐直接在controller引入mapper,这是规范,还是老老实实写service吧。
detail.jsp
<div class="title2">发布时间:${blog.createDate} 日志类别:${blogType}</div>
成果
搞定。
新需求
刚才的一套操作行云流水一般,现在我们来思考一个问题。假如我从数据库查询出一个List,需要给这个List额外增加一个字段,这个新字段需要从别的表里面查询,该怎么办?
比如,我现在要在类型管理页面增加对应类型的日记数量。
这是类型管理的页面。
我们打算加一列,显示文章的总数量。
一个简单的思路就是,先获取类型的列表,然后一次按照类型去查询对应文章的数量。
页面用的是axios异步查询的数据。
getData(){
var index = layer.load(1); //添加laoding,0-2两种方式
axios.post('${basePath}/sys-blog-type/selectAll',{}).then(r =>{
layer.close(index); //返回数据关闭loading
if(r.data.code != '0000'){
layer.msg(r.data.message,{icon:2});
return;
}
console.log(r.data.data);
this.listData = r.data.data;
}).catch(error => {
layer.msg(error.response.status,{icon:2});
layer.close(index); //返回数据关闭loading
})
},
SysBlogTypeController
@RequestMapping("/selectAll")
public List<SysBlogType> selectAll(){
return sysBlogTypeService.selectAll();
}
SysBlogTypeServiceImpl
@Override
public List<SysBlogType> selectAll() {
QueryWrapper<SysBlogType> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("user_id", StpUtil.getLoginId());
return sysBlogTypeMapper.selectList(queryWrapper);
}
代码一目了然,就是结合MybatisPlus做了条件查询。 我们通过controller发现,返回给前端的是List,我们需要增加一列,就需要在这里添加一个字段。
@TableField(exist = false)
private Integer blogNumber;
加上注解@TableField(exist = false)
是因为这个字段只是返回给前端用的,不需要和数据库表做绑定。
修改service
@Autowired
BlogMapper blogMapper;
@Override
public List<SysBlogType> selectAll() {
QueryWrapper<SysBlogType> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("user_id", StpUtil.getLoginId());
List<SysBlogType> sysBlogTypes = sysBlogTypeMapper.selectList(queryWrapper);
sysBlogTypes.forEach(e -> {
Integer typeId = e.getId();
Integer count = blogMapper.selectCount(new LambdaQueryWrapper<TblSynBlog>()
.eq(TblSynBlog::getBlogType, typeId));
e.setBlogNumber(count);
});
return sysBlogTypes;
}
这几行代码是遍历博客类型,计算每个类型下的博客数量,并将数量设置到博客类型实体类中的一个blogNumber属性中。
页面代码修改:
效果:
目的是达到了,但是假如类型非常多,就会导致for循环耗时过长。所以,我们一般不推荐在for循环里面再去查询数据库的。
优化:我们可以先把博客信息查询出来,然后用内存去计算。
@Override
public List<SysBlogType> selectAll() {
// 创建查询条件对象
QueryWrapper<SysBlogType> queryWrapper = new QueryWrapper<>();
// 设置查询条件:用户ID等于当前登录用户的ID
queryWrapper.eq("user_id", StpUtil.getLoginId());
// 查询符合条件的博客分类列表
List<SysBlogType> sysBlogTypes = sysBlogTypeMapper.selectList(queryWrapper);
// 获取所有博客分类的ID
Set<Integer> blogIds = sysBlogTypes.stream().map(SysBlogType::getId).collect(Collectors.toSet());
// 根据博客分类ID查询对应的博客列表
List<TblSynBlog> tblSynBlogs = blogMapper.selectList(new LambdaQueryWrapper<TblSynBlog>()
.in(TblSynBlog::getBlogType, blogIds));
// 将博客列表按照分类ID进行分组
Map<String, List<TblSynBlog>> tblSynBlogsMap = tblSynBlogs.stream().collect(Collectors.groupingBy(TblSynBlog::getBlogType));
// 遍历博客分类列表,设置每个博客分类对应的博客数量
sysBlogTypes.forEach(e -> {
List<TblSynBlog> synBlogs = tblSynBlogsMap.get(e.getId() + "");
if (synBlogs != null) {
e.setBlogNumber(synBlogs.size());
} else {
e.setBlogNumber(0);
}
});
// 返回博客分类列表
return sysBlogTypes;
}
数据不多的话,看不出啥,但是如果数据很多,性能会有一个显著的提升。
源码下载
这个案例我是在springboot日记本系统里面完成了,有需要源码的小伙伴直接clone这个项目即可。
文字教程:
https://blog.csdn.net/weixin_39570751/category_11699146.htmlhttps://blog.csdn.net/weixin_39570751/category_11699146.html
https://gitee.com/skyblue0678/diary