|
@@ -0,0 +1,227 @@
|
|
|
+package com.fdkankan.mongodb.service.impl;
|
|
|
+
|
|
|
+import cn.hutool.core.util.ObjectUtil;
|
|
|
+import com.fdkankan.mongodb.base.BaseRequestMongo;
|
|
|
+import com.fdkankan.mongodb.base.MongoPageResult;
|
|
|
+import com.fdkankan.mongodb.service.MongodbBaseService;
|
|
|
+import com.mongodb.client.result.DeleteResult;
|
|
|
+import org.apache.commons.lang3.StringUtils;
|
|
|
+import org.bson.Document;
|
|
|
+import org.bson.types.ObjectId;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.data.domain.Sort;
|
|
|
+import org.springframework.data.geo.GeoResults;
|
|
|
+import org.springframework.data.mapping.MappingException;
|
|
|
+import org.springframework.data.mongodb.core.MongoTemplate;
|
|
|
+import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
|
|
+import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
|
|
+import org.springframework.data.mongodb.core.query.Criteria;
|
|
|
+import org.springframework.data.mongodb.core.query.NearQuery;
|
|
|
+import org.springframework.data.mongodb.core.query.Query;
|
|
|
+import org.springframework.data.util.Pair;
|
|
|
+import org.springframework.stereotype.Component;
|
|
|
+import org.springframework.util.Assert;
|
|
|
+
|
|
|
+import javax.annotation.PostConstruct;
|
|
|
+import java.lang.reflect.ParameterizedType;
|
|
|
+import java.util.Collections;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Locale;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+/**
|
|
|
+ * @author Xiewj
|
|
|
+ * @date 2021/11/15
|
|
|
+ * Mongodb工具类
|
|
|
+ */
|
|
|
+@Component
|
|
|
+public class MongodbBaseServiceImpl<T> implements MongodbBaseService<T> {
|
|
|
+
|
|
|
+ public static MongodbBaseServiceImpl mongodbBaseService;
|
|
|
+
|
|
|
+
|
|
|
+ @PostConstruct
|
|
|
+ public void init() {
|
|
|
+ mongodbBaseService = this;
|
|
|
+ mongodbBaseService.mongoTemplate = this.mongoTemplate;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private MongoTemplate mongoTemplate;
|
|
|
+
|
|
|
+
|
|
|
+ private static final int FIRST_PAGE_NUM = 1;
|
|
|
+ private static final String ID = "_id";
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 分页查询.
|
|
|
+ *
|
|
|
+ * @param query Mongo Query对象,构造你自己的查询条件.
|
|
|
+ * @param page#mapper 映射器,你从db查出来的list的元素类型是entityClass, 如果你想要转换成另一个对象,比如去掉敏感字段等,可以使用mapper来决定如何转换.
|
|
|
+ * @param page#pageSize 分页的大小.
|
|
|
+ * @param page#pageNum 当前页.
|
|
|
+ * @param page#lastId 条件分页参数, 区别于skip-limit,采用find(_id>lastId).limit分页.
|
|
|
+ * 如果不跳页,像朋友圈,微博这样下拉刷新的分页需求,需要传递上一页的最后一条记录的ObjectId。 如果是null,则返回pageNum那一页.
|
|
|
+ * @return PageResult,一个封装page信息的对象.
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public MongoPageResult<T> pageQuery(BaseRequestMongo page, Query query) {
|
|
|
+ //分页逻辑
|
|
|
+ long total = mongoTemplate.count(query, getTClass());
|
|
|
+ final Integer pages = (int) Math.ceil(total / (double) page.getPageSize());
|
|
|
+ if (page.getPageNum() <= 0 || page.getPageNum() > pages) {
|
|
|
+ page.setPageNum(FIRST_PAGE_NUM);
|
|
|
+ }
|
|
|
+ final Criteria criteria = new Criteria();
|
|
|
+ if (StringUtils.isNotBlank(page.getLastId())) {
|
|
|
+ if (page.getPageNum() != FIRST_PAGE_NUM) {
|
|
|
+ criteria.and(ID).gt(new ObjectId(page.getLastId()));
|
|
|
+ }
|
|
|
+ query.limit(page.getPageSize());
|
|
|
+ } else {
|
|
|
+ int skip = page.getPageSize() * (page.getPageNum() - 1);
|
|
|
+ query.skip(skip).limit(page.getPageSize());
|
|
|
+ }
|
|
|
+ List<T> entityList=null;
|
|
|
+ if (page.getSortBy().toUpperCase(Locale.ROOT).equals(Sort.Direction.DESC.name())){
|
|
|
+ entityList =mongoTemplate
|
|
|
+ .find(query.addCriteria(criteria)
|
|
|
+ .with( Sort.by(Collections.singletonList(new Sort.Order(Sort.Direction.DESC, page.getOrderBy())))),
|
|
|
+ getTClass());
|
|
|
+ }else {
|
|
|
+ entityList=mongoTemplate
|
|
|
+ .find(query.addCriteria(criteria)
|
|
|
+ .with( Sort.by(Collections.singletonList(new Sort.Order(Sort.Direction.ASC, page.getOrderBy())))),
|
|
|
+ getTClass());
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ MongoPageResult<T> mongoPageResult = new MongoPageResult<>();
|
|
|
+ mongoPageResult.setTotal(total);
|
|
|
+ mongoPageResult.setPages(pages);
|
|
|
+ mongoPageResult.setPageSize(page.getPageSize());
|
|
|
+ mongoPageResult.setPageNum(page.getPageNum());
|
|
|
+ mongoPageResult.setList(entityList.stream().collect(Collectors.toList()));
|
|
|
+ return mongoPageResult;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public long getCount(Query query) {
|
|
|
+ return mongoTemplate.count(query, getTClass());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public T save(T t) {
|
|
|
+ return mongoTemplate.save(t);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public T insert(T t) {
|
|
|
+ return mongoTemplate.insert(t);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public DeleteResult delete(T t) {
|
|
|
+ return mongoTemplate.remove(t);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public DeleteResult deleteById(Object id) {
|
|
|
+ T t = mongoTemplate.findById(id, getTClass());
|
|
|
+ if (ObjectUtil.isNotNull(t)){
|
|
|
+ return delete(t);
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public DeleteResult delete(Query query) {
|
|
|
+ return mongoTemplate.remove(query, getTClass());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public T update(T t) {
|
|
|
+ return mongoTemplate.save(t);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public T findById(Object id) {
|
|
|
+ return mongoTemplate.findById(id, getTClass());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public List<T> findAll() {
|
|
|
+ return mongoTemplate.findAll(getTClass());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public List<T> find(Query query) {
|
|
|
+ return mongoTemplate.find(query, getTClass());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public GeoResults<T> geoNear(NearQuery query) {
|
|
|
+ GeoResults<T> geoResults = mongoTemplate.geoNear(query, getTClass());
|
|
|
+ return geoResults;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public T findOne(Query query) {
|
|
|
+ return mongoTemplate.findOne(query,getTClass());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean exists(Query query) {
|
|
|
+ return mongoTemplate.exists(query, getTClass());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean exists(T t) {
|
|
|
+ return exists(getIdQueryFor(t));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean exitsById(Object id) {
|
|
|
+ return exists(findById(id));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public long count(Query query) {
|
|
|
+ return mongoTemplate.count(query, getTClass());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Class<T> getTClass() {
|
|
|
+ Class<T> tClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
|
|
|
+ return tClass;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Pair<String, Object> extractIdPropertyAndValue(Object object) {
|
|
|
+ Assert.notNull(object, "Id cannot be extracted from 'null'.");
|
|
|
+ Class<?> objectType = object.getClass();
|
|
|
+ if (object instanceof Document) {
|
|
|
+ return Pair.of("_id", ((Document) object).get("_id"));
|
|
|
+ } else {
|
|
|
+ MongoPersistentEntity<?> entity = (MongoPersistentEntity) mongoTemplate.getConverter().getMappingContext().getPersistentEntity(objectType);
|
|
|
+ if (entity != null && entity.hasIdProperty()) {
|
|
|
+ MongoPersistentProperty idProperty = (MongoPersistentProperty) entity.getIdProperty();
|
|
|
+ return Pair.of(idProperty.getFieldName(), entity.getPropertyAccessor(object).getProperty(idProperty));
|
|
|
+ } else {
|
|
|
+ throw new MappingException("No id property found for object of type " + objectType);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Query getIdQueryFor(Object object) {
|
|
|
+ Pair<String, Object> id = this.extractIdPropertyAndValue(object);
|
|
|
+ return new Query(Criteria.where((String) id.getFirst()).is(id.getSecond()));
|
|
|
+ }
|
|
|
+
|
|
|
+}
|