springboot整合MongoDB以及对mongoTemplate进一步的封装

前言

业务需要使用到MongoDB,因此将整合过程一一记录。由于原生template操作并不直观,以及操作方式与传统sql数据库有差别。这里将template做进一步封装,使其操作风格尽可能与传统数据DAO一致,对上层屏蔽数据库操作的差异。

springboot整合MongoDB

pom版本依赖信息

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.2.5.RELEASE</version>
		<relativePath/> 
	</parent>
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-mongodb</artifactId>
            <version>2.1.1.RELEASE</version>
        </dependency>

properties文件配置

	spring.data.mongo.uri=mongodb://localhost:27017/test
	若有密码认证则配置如下
	spring.data.mongo.uri=mongodb://username:password@localhost:27017/datasource

mongodb与springboot整合config配置

@Configuration
public class MongoDBConfig {

    @Value("${spring.data.mongo.uri}")
    private String uri;

    @Bean
    public MappingMongoConverter mappingMongoConverter(MongoMappingContext mongoMappingContext) {
        DefaultDbRefResolver dbRefResolver = new DefaultDbRefResolver(dbFactory());
        MappingMongoConverter converter = new MappingMongoConverter(dbRefResolver, mongoMappingContext);
        converter.setTypeMapper(new DefaultMongoTypeMapper(null));
        // 去除写入mongodb时的_class字段
        return converter;
    }

    @Bean
    public MongoDbFactory dbFactory() {
        return new SimpleMongoClientDbFactory(uri);
    }
}

对mongoTemplate做进一步封装

目的对上层使用者屏蔽不同的数据的操作差异。

创建模板接口

package com.onecloud.wm.core.db;

import com.onecloud.wm.core.db.mongo.MongoFilter;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;

import java.util.List;
import java.util.Map;

/**
 * db操作模板
 * 
 * @author wm
 * @date 2021/09/17
 */
public interface IDbTemplate {

    /**
     * 批量增加
     * 
     * @param list 集合
     * @param collectionName 表名
     * @return 结果
     */
    boolean batchSave(List list, String collectionName);

    /**
     * 增加
     * 
     * @param obj 对象
     * @return 结果
     */
    boolean save(Object obj);

    /**
     * 删除
     * 
     * @param obj 对象
     * @return 结果
     */
    boolean remove(Object obj);

    /**
     * 更新
     * 
     * @param objClazz 对象类
     * @param valueMap 条件map
     * @param updateMap 更新map
     * @return 结果
     */
    boolean update(Class objClazz, Map<String, Object> valueMap, Map<String, Object> updateMap);

    /**
     * 按属性过滤条件列表查找对象列表.
     * 
     * @param objClazz 表对象类
     * @param valueMap 条件map
     */
    Object findUniqueBy(Class objClazz, Map<String, Object> valueMap);

    /**
     * 条件统计数量
     * 
     * @param objClazz 表对象类
     * @param valueMap 条件map
     * @return 数据量
     */
    long count(Class objClazz, Map<String, Object> valueMap);

    /**
     * 按属性过滤条件列表查找对象列表.
     * 
     * @param objClazz 表对象类
     * @param valueMap 条件map
     */
    List find(Class objClazz, Map<String, Object> valueMap);

    /**
     * 按属性过滤条件列表分页查找对象.
     * 
     * @param objClazz 表对象类
     * @param pageRequest 分页条件
     * @param valueMap 条件map
     */
    PageImpl findPage(Class objClazz, PageRequest pageRequest, Map<String, Object> valueMap);

    /**
     * 按属性过滤条件列表查找对象列表.
     *
     * @param objClazz 表对象类
     * @param filters 条件过滤器
     */
    List find(Class objClazz, List<MongoFilter> filters);
}

增加MongoDbTemplate对IDbTemplate实现类

@Primary注解用于如果有多个实现类,告知spring优先使用此实现
@Component将该实现类交给sping容器管理

以obj对象形式保存数据。将对象的属性为key,以需要属性数据位value组装成map,对数据进行改查操作。
将map以及将自定义MongoFilter转成MongoDB规范查询语言。具体核心代码如下文 查询转换核心

package com.onecloud.wm.core.db.mongo;

import com.onecloud.wm.core.db.IDbTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

import java.util.List;
import java.util.Map;

/**
 * mongo 操作模板
 * 
 * @author wm
 * @date 2021/09/17
 */
@Component
@Primary
public class MongoDbTemplate implements IDbTemplate {

    @Autowired
    private MongoTemplate mongoTemplate;

    @Override
    public boolean batchSave(List list, String collectionName) {
        mongoTemplate.insert(list, collectionName);
        return true;
    }

    @Override
    public boolean save(Object obj) {
        mongoTemplate.save(obj);
        return true;
    }

    @Override
    public boolean remove(Object obj) {
        return mongoTemplate.remove(obj).getDeletedCount() > 0;

    }

    @Override
    public boolean update(Class objClazz, Map<String, Object> valueMap, Map<String, Object> updateMap) {
        Criteria criteria = MongoQueryTool.buildCriteria(valueMap);
        Assert.notNull(criteria, "Criteria must not be null!");
        Query query = Query.query(criteria);
        Update update = MongoQueryTool.buildUpdate(updateMap);
        return mongoTemplate.updateFirst(query, update, objClazz).getModifiedCount() > 0;

    }

    @Override
    @SuppressWarnings("unchecked")
    public Object findUniqueBy(Class objClazz, Map<String, Object> valueMap) {
        Criteria criteria = MongoQueryTool.buildCriteria(valueMap);
        Assert.notNull(criteria, "Criteria must not be null!");
        Query query = Query.query(criteria);
        return mongoTemplate.findOne(query, objClazz);
    }

    @Override
    public long count(Class objClazz, Map<String, Object> valueMap) {
        Criteria criteria = MongoQueryTool.buildCriteria(valueMap);
        Assert.notNull(criteria, "Criteria must not be null!");
        Query query = Query.query(criteria);
        return mongoTemplate.count(query, objClazz);
    }

    @Override
    @SuppressWarnings("unchecked")
    public List find(Class objClazz, Map<String, Object> valueMap) {
        Criteria criteria = MongoQueryTool.buildCriteria(valueMap);
        Assert.notNull(criteria, "Criteria must not be null!");
        Query query = Query.query(criteria);
        return mongoTemplate.find(query, objClazz);
    }

    @Override
    @SuppressWarnings("unchecked")
    public PageImpl findPage(Class objClazz, PageRequest pageRequest, Map<String, Object> valueMap) {
        Criteria criteria = MongoQueryTool.buildCriteria(valueMap);
        Assert.notNull(criteria, "Criteria must not be null!");
        long count = count(objClazz, valueMap);
        Query query = Query.query(criteria);
        query.with(pageRequest);
        List list = mongoTemplate.find(query, objClazz);
        return new PageImpl(list, pageRequest, count);
    }

    @Override
    @SuppressWarnings("unchecked")
    public List find(Class objClazz, List<MongoFilter> filters) {
        Criteria criteria = MongoQueryTool.buildCriteria(filters);
        Assert.notNull(criteria, "Criteria must not be null!");
        Query query = Query.query(criteria);
        return mongoTemplate.find(query, objClazz);
    }

}

查询转换核心

MongoFilter具体类

package com.onecloud.wm.core.db.mongo;

/**
 * mongo 过滤条件封装
 * 
 * @author wm
 * @date 2021/09/17
 */
public class MongoFilter {

    private Object matchValue = null;
    private MatchType matchType = null;
    private String propertyName = null;

    public MongoFilter() {}

    public MongoFilter(String propName, MatchType matchType, Object value) {
        this.matchType = matchType;
        this.propertyName = propName;
        this.matchValue = value;
    }

    /**
     * 获取比较方式.
     */
    public MatchType getMatchType() {
        return matchType;
    }

    /**
     * 获取比较值.
     */
    public Object getMatchValue() {
        return matchValue;
    }

    /**
     * 获取比较属性名称.
     */
    public String getPropertyName() {
        return propertyName;
    }

    /** 属性比较类型. */
    public enum MatchType {
        EQ, LIKE, LT, GT, LE, GE, IN, NE
    }

}

查询转换工具类


package com.onecloud.scada.school.core.db.mongo;

import com.onecloud.scada.model.util.CommonTool;
import com.onecloud.scada.school.core.db.mongo.MongoFilter.MatchType;
import com.onecloud.scada.utils.AssertUtils;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Update;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * mongo查询规则转换工具
 * 
 * @author wm
 * @date 2021/09/17
 */
public class MongoQueryTool {

    /**
     * map转MongoDB查询语句规则
     * 
     * @param paramMap map
     */
    public static Criteria buildCriteria(Map<String, Object> paramMap) {
        if (paramMap == null) {
            return null;
        }
        Criteria criteria = null;
        int i = 0;
        for (String key : paramMap.keySet()) {
            Object value = paramMap.get(key);
            if (i == 0) {
                if (value instanceof Collection) {
                    criteria = Criteria.where(key).in((List)value);
                } else {
                    criteria = Criteria.where(key).is(value);
                }
            } else {
                if (value instanceof Collection) {
                    criteria.and(key).in((List)value);
                } else {
                    criteria.and(key).is(value);
                }
            }
            i++;
        }
        return criteria;
    }

    /**
     * map转MongoDB查询语句规则
     *
     * @param filters filters
     */
    public static Criteria buildCriteria(List<MongoFilter> filters) {
        if (CommonTool.isNullOrEmpty(filters)) {
            return null;
        }
        Criteria criteria = new Criteria();
        int i = 0;
        List<Criteria> criteriaList = new ArrayList<>();
        for (MongoFilter filter : filters) {
            if (i == 0) {
                criteria = buildCriterion(filter.getPropertyName(), filter.getMatchValue(), filter.getMatchType());
            } else {
                criteriaList
                    .add(buildCriterion(filter.getPropertyName(), filter.getMatchValue(), filter.getMatchType()));
            }
            i++;
        }
        if (CommonTool.isNonEmpty(criteriaList)) {
            criteria = criteria.andOperator(criteriaList.toArray(new Criteria[] {}));
        }
        return criteria;
    }

    /**
     * map转MongoDB更新语句规则
     *
     * @param paramMap map
     */
    public static Update buildUpdate(Map<String, Object> paramMap) {
        if (paramMap == null) {
            return null;

        }
        Update update = new Update();
        for (String key : paramMap.keySet()) {
            Object value = paramMap.get(key);
            update.set(key, value);
        }
        return update;
    }

    /**
     * 按属性条件参数创建Criterion,辅助函数.
     */
    public static Criteria buildCriterion(String propertyName, Object propertyValue, MatchType matchType) {
        AssertUtils.hasText(propertyName, "propertyName不能为空");
        Criteria criteria = new Criteria(propertyName);
        // 根据MatchType构造criterion
        switch (matchType) {
            case EQ:
                criteria = criteria.is(propertyValue);
                break;
            case NE:
                criteria = criteria.ne(propertyValue);
                break;
            case LIKE:
                String pattern = ".*" + propertyValue + ".*";
                criteria = criteria.regex(pattern);
                break;
            case LE:
                criteria = criteria.lte(propertyValue);
                break;
            case LT:
                criteria = criteria.lt(propertyValue);
                break;
            case GE:
                criteria = criteria.gte(propertyValue);
                break;
            case GT:
                criteria = criteria.gt(propertyValue);
                break;
            case IN:
                criteria = criteria.in((List)propertyValue);
                break;
            default:
                break;
        }
        return criteria;
    }
}


后续

可进一步封装MongoDBDao层,以及MongoDBService,完成基础的实现。后续扩展新的表,可直接实继承MongoDBService实现类,使用默认操作
见:像传统数据库DAO一样操作MongoDB

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值