首页 > 其他分享 >SpringBoot MongoTemplate 实现分页

SpringBoot MongoTemplate 实现分页

时间:2023-12-12 19:31:29浏览次数:29  
标签:SpringBoot localPage args MongoTemplate org query import 分页

一、MongoTemplate 实现分页

springboot集成Mongodb好像没有现成的分页工具,只能自己先查总数再查数据,需要进行两次查询。

例如:

@Test
public void test_119() throws Exception{
    Query query = new Query();
    long total = mongoTemplate.count(query, Dog.class);
    query.with(PageRequest.of(0,3));
    List<Dog> dogList = mongoTemplate.find(query, Dog.class);
    System.out.println("总行数:"+total);
    System.out.println(JSON.toJSONString(dogList, SerializerFeature.PrettyFormat));
}

上述代码查询了dog列表的第0页,每页3条数据。运行结果如下:SpringBoot MongoTemplate 实现分页_spring

PS:注意PageRequest起始页码为0。与MySQL起始页为1不同。

二、自定义AOP实现分页工具

可以发现分页都是这个逻辑:先查总数、添加分页信息、再查列表数据。

由于开发中同时用到了MyBatis,MyBatis有自己的分页插件 PageHelper 。PageHelper还是很好用的,只需要PageHelper.startPage(0,3); 之后的首次查询就自带分页了。

那能否让 PageHelper 也对 MongoTemplate 有效呢?

PageHelper是通过ThreadLocal来传递数据的,我们可以通过自定义一个AOP对MongoTemplate的查询方法进行增强即可。

首先引入AOP相关starter:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

编写切面类:

package org.example.aop;

import com.github.pagehelper.Page;
import com.github.pagehelper.SqlUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Component;
import java.util.List;

@Aspect
@Component
public class MongoTemplateAop {

    @Autowired
    private MongoTemplate mongoTemplate;

    @Pointcut("execution(public * org.springframework.data.mongodb.core.MongoTemplate.find(..))")
    public void findPoint(){}

    @Pointcut("execution(public * org.springframework.data.mongodb.core.MongoTemplate.findAll(..))")
    public void findAllPoint(){}

    @Around("findPoint()")
    public Object findPointAround(ProceedingJoinPoint pjp){
        try {
            Object[] args = pjp.getArgs();
            // 是否开启了分页查询
            Page<Object> localPage = SqlUtil.getLocalPage();
            if (localPage != null && args[0] instanceof Query) {
                Query query = (Query) args[0];
                int pageNum = localPage.getPageNum();
                int pageSize = localPage.getPageSize();

                // 没有主动设置过分页相关的限制时,PageHelper 才生效
                if (query.getLimit() == 0 && query.getSkip() == 0) {
                    // 查询总数
                    long total = 0;
                    Class<?> entityClass = (Class<?>) args[1];
                    if (args.length == 3) {
                        String collectionName = (String) args[2];
                        total = mongoTemplate.count(query, entityClass, collectionName);
                    } else {
                        total = mongoTemplate.count(query, entityClass);
                    }
                    localPage.setTotal(total);

                    // 添加分页条件
                    query.with(PageRequest.of(pageNum - 1, pageSize));
                    List<?> result = (List<?>) pjp.proceed(args);
                    localPage.addAll(result);
                    return localPage;
                }
            }

            // 不分页直接查询
            return pjp.proceed(args);
        } catch (Throwable e) {
            throw new RuntimeException(e);
        } finally {
            // PageHelper 作废
            SqlUtil.clearLocalPage();
        }
    }

    @Around("findAllPoint()")
    public Object findAllPointAround(ProceedingJoinPoint pjp){
        try {
            Object[] args = pjp.getArgs();
            // 是否开启了分页查询
            Page<Object> localPage = SqlUtil.getLocalPage();
            if (localPage != null) {
                Query query = new Query();
                int pageNum = localPage.getPageNum();
                int pageSize = localPage.getPageSize();

                // 没有主动设置过分页相关的限制时,PageHelper 才生效
                if (query.getLimit() == 0 && query.getSkip() == 0) {
                    // 查询总数
                    long total = 0;
                    List<?> result;
                    Class<?> entityClass = (Class<?>) args[0];
                    if (args.length == 2) {
                        String collectionName = (String) args[1];
                        total = mongoTemplate.count(query, entityClass, collectionName);
                        // 分页查询
                        query.with(PageRequest.of(pageNum - 1, pageSize));
                        result = mongoTemplate.find(query, entityClass, collectionName);
                    } else {
                        total = mongoTemplate.count(query, entityClass);
                        // 分页查询
                        query.with(PageRequest.of(pageNum - 1, pageSize));
                        result = mongoTemplate.find(query, entityClass);
                    }
                    localPage.setTotal(total);
                    localPage.addAll(result);
                    return localPage;
                }
            }

            // 不分页直接查询
            return pjp.proceed(args);
        } catch (Throwable e) {
            throw new RuntimeException(e);
        } finally {
            // PageHelper 作废
            SqlUtil.clearLocalPage();
        }
    }

}

使用:

@Test
public void test_82() throws Exception{
    PageHelper.startPage(1,3);
    List<Dog> dogList = mongoTemplate.find(Query.query(Criteria.where("type").is(DogTypeEnum.ROBOT_DOG)), Dog.class);
    // 包装分页信息
    PageInfo<Dog> dogPageInfo = new PageInfo<>(dogList);
    System.out.println(JSON.toJSONString(dogPageInfo, SerializerFeature.PrettyFormat));
}

结果:

SpringBoot MongoTemplate 实现分页_分页_02




标签:SpringBoot,localPage,args,MongoTemplate,org,query,import,分页
From: https://blog.51cto.com/u_16369756/8790475

相关文章

  • select for update在springboot里实现分布式锁
    //mapper,注意,这里的参数最好就是主键或者唯一键,否则产生的是表锁@Select("<script>select*fromfoowhereid=#{id}forupdate</script>")FooselectForUpdateById(@Param("id")Longid);//service,必须加事物,否则selectForUpdateById无法实现分布式锁的作用@Transac......
  • springboot listener、filter登录实战
    转载自:www.javaman.cn博客系统访问:http://175.24.198.63:9090/front/index登录功能1、前端页面采用的是layui-admin框架,文中的验证码内容,请参考作者之前的验证码功能<!DOCTYPEhtml><htmllang="zh"xmlns:th="http://www.thymeleaf.org"><head><title>ds博客</tit......
  • 【转载】Springboot2.x接收参数的多种方式
    参考https://blog.csdn.net/suki_rong/article/details/80445880https://zhuanlan.zhihu.com/p/34597391https://juejin.cn/post/6922469125033820168环境环境版本操作windows10JDK11Springboot2.3.12.RELEASE正文packagecom.example.demo.co......
  • vue 逻辑分页
    <template><div><divclass="paging"><!--数据显示区域--><divclass="data"><!--表格存放数组中的数据,并对数据进行截取,以控制每一页显示的数据量--><!--slice(start,end)不包括end--><el-ta......
  • mybatis-plus使用连表查询分页
    mybatis-plus在进行单表查询时确实很方便,但是一旦我们需要连表查询时,就不得不引用其他插件来进行操作。但是复杂的查询必然会造成我们的代码量往上涨。当然mybatis-plus也不会脱离mybatis原本的特性,比如xml文件来操作数据库。本篇文章记录一下使用mybatis-plus来进行连表查询分......
  • springboot下添加日志模块和设置日志文件输出
    前言日志的使用将通过SLF4J来使用,SLF4J(SimpleLoggingFacadeforJava)是一个为Java应用提供简单日志记录的接口。它的主要目标是在不同的日志系统之间提供一个简单的抽象层,使得应用能够以一种灵活的方式切换日志实现,而不需要修改应用本身的代码。SLF4J不是一个具体的日志实现,而......
  • 【SpringBootWeb入门-9】分层解耦-分层解耦(IOC-DI引入)
    1、分层解耦概念上一节我们讲解了三层架构,我们把web程序分为了三层,分别是Conroller控制层、Service业务逻辑层、DAO数据访问层,这一节我们来讲解分层之后的解耦。解耦的含义就是接触耦合,首先我们来介绍两个概念:内聚、耦合。内聚:软件中各个功能模块内部的功能联系。耦合:衡量软......
  • SpringBoot+Vue实现大文件分块上传
    1.项目背景由于用户需求,需要上传大量图片,只能通过上传压缩包的形式上传,可是压缩包过大时,又会出现上传超时的情况,故需要将压缩包分块上传,然后解压缩图片、若图片过大则再对图片进行压缩。2.分块上传分块上传我在用的时候发现有两种:第一种:分块合并接口全由后端接口生成;第二种:前端......
  • springboot下添加全局异常处理和自定义异常处理
    前言在spring项目中,优雅处理异常,好处是可以将系统产生的全部异常统一捕获处理,自定义的异常也由全局异常来捕获,如果涉及到validator参数校验器使用全局异常捕获也是较为方便。相关代码:GlobalExceptionHandler类:@Slf4j@RestControllerAdvicepublicclassGlobalExceptionHandl......
  • 一文浅入Springboot+mybatis-plus+actuator+Prometheus+Grafana+Swagger2.9.2开发运维
    Swagger是一个规范和完整的框架,用于生成、描述、调用和可视化RESTFUL风格的Web服务,是非常流行的API表达工具。Swagger能够自动生成完善的RESTFULAP文档,,同时并根据后台代码的修改同步更新,同时提供完整的测试页面来调试API。Prometheus是一个开源的服务监控系统和时序数据库......