因为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;
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(basePackages = "com.xxx.xxxx.xxx.xxx.repository", repositoryBaseClass = ExtendSimpleMongoRepository.class)
public class MongoConfig {
}
- 在所需要使用该方法的Repository类中声明该方法:
import com.odianyun.demo.repository.support.MySimpleMongoRepository;
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);
}
- 使用并进行测试:
成功完成所需功能。
|