因为MongoRepository对复杂查询并不友好,所以继承了其实现类增加了一些新的查询方法;
重写MongoRepository的接口实现参照博文实现:https://www.cnblogs.com/sweetchildomine/p/7732766.html
需要完成的功能:

根据是否删除(isDeleted)、时间(createTime)、用户id(userId)三个条件动态的查询结果集,且完成分页,其中,是否删除、用户手机号为精确查询,时间为范围查询,三个参数皆可为空

遇到的问题:

在这里插入图片描述
以上是一个继承了MongoRepository的接口类,可以发现其并未存在范围查询,所以使用MongoRepository的自带方法并不能实现我们需要的功能。

通过JPA的自定义方法可以解决:
在这里插入图片描述
自定义一个创建时间的范围查询,但是存在一个问题就是,参数是动态的,方法名是固定的,这样就需要在业务层根据传入参数的不同做相关的逻辑判断来调不同的方法,差不多要定义八个相关的方法:
ps:Object …… param代表省略的参数

Page<XXX> findByCreateTimeBetweenAndUserIdIsAAndIsDeletedIs(Object …… param);
Page<XXX> findByCreateTimeBetweenAndUserIdIsA(Object …… param);
Page<XXX> findByCreateTimeBetweenAndIsDeletedIs(Object …… param);
Page<XXX> findByUserIdIsAAndIsDeletedIs(Object …… param);
…………

以上就会存在一个弊端,参数越多需要定义的方法名就越多,不支持动态参数;

最终解决方案:

查看MongoRepository的API可以发现一个方法,这个方法既支持动态传参,也支持分页,但弊端是Example不支持范围查询:

<S extends T> Page<S> findAll(Example<S> example, Pageable pageable);

查看此方法的底层实现:

@Override
public <S extends T> Page<S> findAll(final Example<S> example, Pageable pageable) {

	Assert.notNull(example, "Sample must not be null!");
	Assert.notNull(pageable, "Pageable must not be null!");

	Query q = new Query(new Criteria().alike(example)).with(pageable);
	List<S> list = mongoOperations.find(q, example.getProbeType(), entityInformation.getCollectionName());

	return PageableExecutionUtils.getPage(list, pageable,
			() -> mongoOperations.count(q, example.getProbeType(), entityInformation.getCollectionName()));
}

我们可以发现,该方法底层是把Example转换成了Query去查询的,Example支持动态参数不支持范围查询,Query既支持动态参数也支持范围查询,所以,如果我们可以声明一个入参为Query和Pageable的方法就可以实现动态参数查询和范围查询分页了,以下是实现方法:

  • 继承MongoRepository的实现类进行方法扩展:
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.repository.query.MongoEntityInformation;
import org.springframework.data.mongodb.repository.support.SimpleMongoRepository;
import org.springframework.data.repository.support.PageableExecutionUtils;
import org.springframework.util.Assert;

import java.io.Serializable;
import java.util.List;

/**
 * MongoRepository扩展
 * liurui
 * @author liurui
 * @param <T>
 * @param <ID>
 */
public class ExtendSimpleMongoRepository<T, ID extends Serializable> extends SimpleMongoRepository<T, ID> {
    private final MongoOperations mongoOperations;
    private final MongoEntityInformation<T, ID> entityInformation;


    public ExtendSimpleMongoRepository(MongoEntityInformation<T, ID> metadata, MongoOperations mongoOperations) {
        super(metadata, mongoOperations);
        this.entityInformation = metadata;
        this.mongoOperations = mongoOperations;
    }

    public <S extends T> Page<S> findAll(final Example<S> example, final Query query, Pageable pageable) {
        Assert.notNull(example, "Sample must not be null!");
        query.addCriteria((new Criteria()).alike(example)).with(pageable);
        List<S> list = this.mongoOperations.find(query, example.getProbeType(), this.entityInformation.getCollectionName());
        return PageableExecutionUtils.getPage(list, pageable, () -> mongoOperations.count(query, example.getProbeType(),entityInformation.getCollectionName()));
    }

    public <S extends T> Page<T> findAll(Query query, Pageable pageable) {
        query.with(pageable);
        List<T> list = mongoOperations.find(query, entityInformation.getJavaType(), entityInformation.getCollectionName());

        return PageableExecutionUtils.getPage(list, pageable,
                () -> mongoOperations.count(query, entityInformation.getJavaType(), entityInformation.getCollectionName()));
    }
}
  • 修改mongo配置中MongoRepository的实现类:
@Configuration
// 通过@EnableMongoRepositories注解的repositoryBaseClass属性可以更换MongoRepository的实现类,通过mongoTemplateRef可以更换不同的mongoTemplate数据源
@EnableMongoRepositories(basePackages = "com.xxx.xxxx.xxx.xxx.repository", repositoryBaseClass = ExtendSimpleMongoRepository.class)
public class MongoConfig {

	// 以下内容省略
}
  • 在所需要使用该方法的Repository类中声明该方法:
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface SuperVipOpenCardRecordRepository extends MongoRepository<xxxx, Long> {
    Page<xxxx> findAll(Query query, Pageable pageable);
}
  • 使用并进行测试:
    在这里插入图片描述
    在这里插入图片描述

成功完成所需功能。

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐