• Spring Boot 项目中使用 MongoDB


    MongoDB 是一个基于分布式文件存储的数据库。由 C++ 语言编写。旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。

    首先为项目添加 MongoDB 支持。

    Gradle:

    compile("org.springframework.boot:spring-boot-starter-data-mongodb:2.0.5.RELEASE")
    compile("org.mongodb:mongo-java-driver:3.6.4")
    

    Maven:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-mongodb</artifactId>
        <version>2.0.5.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.mongodb</groupId>
        <artifactId>mongo-java-driver</artifactId>
        <version>3.6.4</version>
    </dependency>
    

    MongoTools 类:

    package com.charles.testlibrary.util;
    
    import com.mongodb.MongoClient;
    import com.mongodb.MongoCredential;
    import com.mongodb.ServerAddress;
    import com.mongodb.client.MongoCollection;
    import com.mongodb.client.MongoDatabase;
    import java.util.ArrayList;
    import java.util.List;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class MongoTools {
    
      // mongo环境变量
      private static String host;
      private static String port;
      private static String dbname;
      private static String username;
      private static String password;
    
      public static String getHost() {
        return host;
      }
    
      @Value("${spring.data.mongodb.host}")
      public void setHost(String host) {
        MongoTools.host = host;
      }
    
      public static String getPort() {
        return port;
      }
    
      @Value("${spring.data.mongodb.port}")
      public void setPort(String port) {
        MongoTools.port = port;
      }
    
      public static String getDbname() {
        return dbname;
      }
    
      @Value("${spring.data.mongodb.database}")
      public void setDbname(String dbname) {
        MongoTools.dbname = dbname;
      }
    
      public static String getUsername() {
        return username;
      }
    
      @Value("${spring.data.mongodb.username}")
      public void setUsername(String username) {
        MongoTools.username = username;
      }
    
      public static String getPassword() {
        return password;
      }
    
      @Value("${spring.data.mongodb.password}")
      public void setPassword(String password) {
        MongoTools.password = password;
      }
    
      private static MongoClient client = null;
      private static MongoDatabase db = null;
      private static MongoCollection collection;
    
      public MongoTools() {
      }
    
      /**
       * 获取数据库.
       * @return
       */
      public static MongoDatabase getDb() {
        try {
          if (client == null) {
            init();
          }
          //连接到数据库
          db = client.getDatabase(dbname);
        } catch (Exception e) {
          e.printStackTrace();
        }
        return db;
      }
    
      private static void init() {
        System.out.println("com.mongodb.client.MongoCollection");
        ServerAddress sa = new ServerAddress(host, Integer.parseInt(port));
        List<ServerAddress> sas = new ArrayList<>();
        sas.add(sa);
        MongoCredential mc = MongoCredential.createCredential(username, dbname, password.toCharArray());
        List<MongoCredential> mcs = new ArrayList<>();
        mcs.add(mc);
        //连接服务
        client = new MongoClient(sas, mcs);
      }
    
      /**
       * 建立连接.
       * @param collectionName 数据库
       * @return
       */
      public static MongoCollection getCollection(String collectionName) {
        getDb();
        collection = db.getCollection(collectionName);
        return collection;
      }
    }
    

    MongoService 类:

    package com.charles.testlibrary.core;
    
    
    import com.mongodb.MongoNamespace;
    import com.mongodb.client.FindIterable;
    import com.mongodb.client.MongoCollection;
    import com.mongodb.client.MongoCursor;
    import com.mongodb.client.model.Collation;
    import com.charles.testlibrary.util.MongoTools;
    
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    import java.util.Set;
    import javax.annotation.Resource;
    
    import org.bson.Document;
    import org.springframework.data.domain.Sort;
    import org.springframework.data.domain.Sort.Direction;
    import org.springframework.data.domain.Sort.Order;
    import org.springframework.data.mongodb.core.MongoTemplate;
    import org.springframework.data.mongodb.core.mapreduce.GroupBy;
    import org.springframework.data.mongodb.core.mapreduce.GroupByResults;
    import org.springframework.data.mongodb.core.query.Criteria;
    import org.springframework.data.mongodb.core.query.Update;
    import org.springframework.stereotype.Service;
    
    
    @Service
    public class MongoService {
    
        @Resource
        private MongoTemplate mongoTemplate;
    
        /**
         * 根据key/value计算符合条件的数据数量.
         *
         * @param provalues      value
         * @param collectionName 集合名
         */
        public long countBy(String[] prokeys, Object[] provalues, String collectionName) {
            org.springframework.data.mongodb.core.query.Query query =
                    new org.springframework.data.mongodb.core.query.Query();
            Criteria criteria = new Criteria();
            Criteria[] criterias = new Criteria[prokeys.length];
            for (int i = 0; i < prokeys.length; i++) {
                criterias[i] = Criteria.where(prokeys[i].toString()).is(provalues[i]);
            }
            criteria.andOperator(criterias);
            query.addCriteria(criteria);
            long result = mongoTemplate.count(query, collectionName);
            return result;
        }
    
        /**
         * 查询大于指定条件的数据量.
         *
         * @param prokeys           key
         * @param provalues         value
         * @param greaterThanKeys   大于条件的key
         * @param greaterThanValues 大于条件的value
         * @param collectionName    集合名
         */
        public long countByGt(String[] prokeys, Object[] provalues,
                              String[] greaterThanKeys,
                              Object[] greaterThanValues, String collectionName) {
            org.springframework.data.mongodb.core.query.Query query =
                    new org.springframework.data.mongodb.core.query.Query();
            for (int i = 0; i < prokeys.length; i++) {
                query.addCriteria(Criteria.where(prokeys[i]).is(provalues[i]));
            }
            for (int i = 0; i < greaterThanKeys.length; i++) {
                query.addCriteria(Criteria.where(greaterThanKeys[i]).gt(greaterThanValues[i]));
            }
            return mongoTemplate.count(query, collectionName);
        }
    
        /**
         * 根据key/value查找符合条件的一条数据.
         *
         * @param prokeys        key
         * @param provalues      value
         * @param collectionName 集合名
         * @param orderBy        排序字段
         * @param order          1:升序 -1:降序
         */
        public Map findOne(String[] prokeys, Object[] provalues, String collectionName,
                           String orderBy, Integer order) {
            MongoCollection coll = MongoTools.getCollection(collectionName);
            Map m = new HashMap<>();
            Document doc = new Document();
            for (int i = 0; i < prokeys.length; i++) {
                if (i == 0) {
                    doc.put(prokeys[i], provalues[i]);
                } else {
                    doc.append(prokeys[i], provalues[i]);
                }
            }
            Document sort = new Document();
            if (orderBy != null) {
                sort = new Document(orderBy, order);
            }
            FindIterable iter = coll.find(doc).skip(0).limit(1).sort(sort);
            MongoCursor cursor = iter.iterator();
            if (cursor.hasNext()) {
                m = (Map) cursor.next();
                m.remove("_id");
            }
            return m;
        }
    
        /**
         * 根据key/value获取bean.
         *
         * @param querys         key/value
         * @param collectionName 集合名
         */
        public Object findOne(Map<String, Object> querys, String collectionName, Class clazz) {
            org.springframework.data.mongodb.core.query.Query query =
                    new org.springframework.data.mongodb.core.query.Query();
            for (Map.Entry e : querys.entrySet()) {
                query.addCriteria(Criteria.where(e.getKey().toString()).is(e.getValue()));
            }
            return mongoTemplate.findOne(query, clazz, collectionName);
        }
    
        /**
         * 根据key/value获取bean.
         *
         * @param querys         key/value
         * @param collectionName 集合名
         */
        public <T> T findEntity(Map<String, Object> querys, String collectionName, Class<T> clazz) {
            org.springframework.data.mongodb.core.query.Query query =
                    new org.springframework.data.mongodb.core.query.Query();
            for (Map.Entry e : querys.entrySet()) {
                query.addCriteria(Criteria.where(e.getKey().toString()).is(e.getValue()));
            }
            return mongoTemplate.findOne(query, clazz, collectionName);
        }
    
        /**
         * 根据key/value查找符合条件的一条数据(取出指定字段).
         *
         * @param prokeys        key
         * @param provalues      value
         * @param includeFields  指定字段集合
         * @param collectionName 集合名
         */
        public Map findOneFilterFeilds(String[] prokeys, Object[] provalues, String[] includeFields,
                                       String collectionName) {
            MongoCollection coll = MongoTools.getCollection(collectionName);
            Map m = new HashMap<>();
            Document doc = new Document();
            Document filter = new Document();
            for (int i = 0; i < prokeys.length; i++) {
                if (i == 0) {
                    doc.put(prokeys[i], provalues[i]);
                } else {
                    doc.append(prokeys[i], provalues[i]);
                }
            }
            for (int i = 0; i < includeFields.length; i++) {
                filter.append(includeFields[i], true);
            }
            FindIterable iter = coll.find(doc).projection(filter).skip(0).limit(1);
            MongoCursor cursor = iter.iterator();
            if (cursor.hasNext()) {
                m = (Map) cursor.next();
                m.remove("_id");
            }
            return m;
        }
    
        /**
         * 指定key/value分页取出数据.
         *
         * @param prokeys        key
         * @param provalues      value
         * @param collectionName 集合名
         * @param skip           跳过前面n条数据
         * @param size           取m条数据
         * @param orderBy        排序字段
         * @param order          1:升序 -1:降序
         */
        public List<Map<String, Object>> findByPage(String[] prokeys, Object[] provalues,
                                                    String collectionName,
                                                    int skip, int size, String orderBy, Integer order) {
            MongoCollection coll = MongoTools.getCollection(collectionName);
            List<Map<String, Object>> list = new ArrayList<>();
            Document doc = new Document();
            if (prokeys != null && provalues != null) {
                for (int i = 0; i < prokeys.length; i++) {
                    doc.append(prokeys[i], provalues[i]);
                }
            }
            long totalCount = coll.count();
            FindIterable iter = coll.find(doc).skip(skip).limit(size).sort(new Document(orderBy, order));
            MongoCursor cursor = iter.iterator();
            while (cursor.hasNext()) {
                Map m = (Map) cursor.next();
                m.remove("_id");
                list.add(m);
            }
            return list;
        }
    
        /**
         * 指定key/value分页取出数据.
         *
         * @param filter         筛选条件
         * @param collectionName 集合名
         * @param skip           跳过前面n条数据
         * @param size           取m条数据
         * @param orderBy        排序字段
         * @param order          1:升序 -1:降序
         */
        public Map<String, Object> findByPage(Map<String, Object> filter, Map<String, Object> childFilter,
                                              String collectionName, int skip, int size,
                                              String orderBy, Integer order) {
            MongoCollection coll = MongoTools.getCollection(collectionName);
            List<Map<String, Object>> list = new ArrayList<>();
            Document doc = new Document();
            List<Document> docList = new ArrayList<Document>();
            Set<String> keySet = filter.keySet();
            for (String key : keySet) {
                docList.add(new Document(key, filter.get(key)));
            }
            Collation.Builder numericOrdering = Collation.builder().locale("zh").numericOrdering(true);
            Collation collation = numericOrdering.build();
            FindIterable<Document> findIterable = coll.find(new Document("$and", docList)).skip(skip)
                    .limit(size).collation(collation).sort(new Document(orderBy, order));
            long totalCount = coll.count(new Document("$and", docList));
            if (childFilter.size() != 0) {
                // 子级查找
                List<Document> childList = new ArrayList<>();
                Set<String> childKeySet = childFilter.keySet();
                for (String key : childKeySet) {
                    childList.add(new Document(key, childFilter.get(key)));
                }
                findIterable = coll.find(new Document("$and", childList)).skip(skip)
                        .limit(size).collation(collation).sort(new Document(orderBy, order));
                totalCount = coll.count(new Document("$and", childList));
            }
            MongoCursor cursor = findIterable.iterator();
            while (cursor.hasNext()) {
                Map m = (Map) cursor.next();
                m.remove("_id");
                m.remove("_class");
                list.add(m);
            }
            Map<String, Object> totalRecords = new HashMap();
            totalRecords.put("paperList", list);
            totalRecords.put("totalRecords", totalCount);
            return totalRecords;
        }
    
        /**
         * 指定key/value分页取出数据.
         */
        public <T> List<T> findByPage(int pageNum, int size, String collectionName, Class<T> clazz) {
            if (pageNum < 1) {
                pageNum = 1;
            }
            org.springframework.data.mongodb.core.query.Query query =
                    new org.springframework.data.mongodb.core.query.Query();
            query.skip((pageNum - 1) * size);
            query.limit(size);
            return mongoTemplate.find(query, clazz, collectionName);
        }
    
        /**
         * 指定key/value取出所有数据,使用in条件,传入Object[]类型数组.
         *
         * @param prokeys        key
         * @param provalues      value
         * @param collectionName 集合名
         * @param orderBy        排序字段
         * @param order          1:升序 -1:降序
         */
        public List<Map> findAllWithIn(String[] prokeys, Object[] provalues,
                                       String collectionName, String orderBy, Integer order) {
            org.springframework.data.mongodb.core.query.Query query =
                    new org.springframework.data.mongodb.core.query.Query();
            for (int i = 0; i < prokeys.length; i++) {
                if (provalues[i] instanceof Object[]) {
                    query.addCriteria(Criteria.where(prokeys[i]).in((Object[]) provalues[i]));
                } else {
                    query.addCriteria(Criteria.where(prokeys[i]).is(provalues[i]));
                }
            }
            if (orderBy != null && order != null) {
                Direction direction;
                if (order < 0) {
                    direction = Direction.DESC;
                } else {
                    direction = Direction.ASC;
                }
                query.with(new Sort(new Order(direction, orderBy)));
            }
            return mongoTemplate.find(query, Map.class, collectionName);
        }
    
        /**
         * 指定key/value取出所有数据,使用in条件,传入Object[]类型数组.
         *
         * @param prokeys        key
         * @param provalues      value
         * @param collectionName 集合名
         * @param orderBy        排序字段
         * @param order          1:升序 -1:降序
         */
        public List findAllWithIn(String[] prokeys, Object[] provalues,
                                  String collectionName, Class entityClass,
                                  String orderBy, Integer order) {
            org.springframework.data.mongodb.core.query.Query query =
                    new org.springframework.data.mongodb.core.query.Query();
            for (int i = 0; i < prokeys.length; i++) {
                if (provalues[i] instanceof Object[]) {
                    query.addCriteria(Criteria.where(prokeys[i]).in((Object[]) provalues[i]));
                } else {
                    query.addCriteria(Criteria.where(prokeys[i]).is(provalues[i]));
                }
            }
            if (orderBy != null && order != null) {
                Direction direction;
                if (order < 0) {
                    direction = Direction.DESC;
                } else {
                    direction = Direction.ASC;
                }
                query.with(new Sort(new Order(direction, orderBy)));
            }
            return mongoTemplate.find(query, entityClass, collectionName);
        }
    
        /**
         * 指定key/value取出所有数据.
         *
         * @param prokeys        key
         * @param provalues      value
         * @param collectionName 集合名
         * @param orderBy        排序字段
         * @param order          1:升序 -1:降序
         */
        public List<Map<String, Object>> findAll(String[] prokeys, Object[] provalues,
                                                 String collectionName, String orderBy, Integer order) {
            MongoCollection coll = MongoTools.getCollection(collectionName);
            List<Map<String, Object>> list = new ArrayList<>();
            Document doc = new Document();
            for (int i = 0; i < prokeys.length; i++) {
                doc.append(prokeys[i], provalues[i]);
            }
            FindIterable iter = coll.find(doc).sort(new Document(orderBy, order));
            MongoCursor cursor = iter.iterator();
            while (cursor.hasNext()) {
                Map m = (Map) cursor.next();
                m.remove("_id");
                list.add(m);
            }
            return list;
        }
    
        /**
         * 指定key/value取出所有数据.
         *
         * @param filter         筛选条件
         * @param collectionName 集合名
         * @param orderBy        排序字段
         * @param order          1:升序 -1:降序
         */
        public List<Map<String, Object>> findAll(Map<String, Object> filter,
                                                 Map<String, Object> childFilter,
                                                 String collectionName, String orderBy, Integer order) {
            MongoCollection coll = MongoTools.getCollection(collectionName);
            List<Map<String, Object>> list = new ArrayList<>();
            List<Document> docList = new ArrayList<>();
            Set<String> keySet = filter.keySet();
            for (String key : keySet) {
                docList.add(new Document(key, filter.get(key)));
            }
            Collation.Builder numericOrdering = Collation.builder().locale("zh").numericOrdering(true);
            Collation collation = numericOrdering.build();
            FindIterable<Document> findIterable = coll.find(new Document("$and", docList))
                    .collation(collation).sort(new Document(orderBy, order));
            if (childFilter.size() != 0) {
                // 子级查找
                List<Document> childList = new ArrayList<>();
                Set<String> childKeySet = childFilter.keySet();
                for (String key : childKeySet) {
                    childList.add(new Document(key, childFilter.get(key)));
                }
                findIterable = coll.find(new Document("$and", childList)).collation(collation)
                        .sort(new Document(orderBy, order));
            }
            MongoCursor cursor = findIterable.iterator();
            while (cursor.hasNext()) {
                Map m = (Map) cursor.next();
                m.remove("_id");
                m.remove("_class");
                list.add(m);
            }
            return list;
        }
    
        /**
         * 指定key/value取出所有数据(指定字段且多排序).
         *
         * @param prokeys        key
         * @param provalues      value
         * @param includeFields  指定字段
         * @param collectionName 集合名
         * @param orderBys       排序字段
         * @param orders         1:升序 -1:降序
         */
        public List<Map<String, Object>> findAllByArrOrderAndProjection(
                String[] prokeys, Object[] provalues, String[] includeFields,
                String collectionName, String[] orderBys,
                Integer[] orders) {
            List<Map<String, Object>> list = new ArrayList<>();
            Document doc = new Document();
            Document filter = new Document();
            Document order = new Document();
            for (int i = 0; i < prokeys.length; i++) {
                doc.append(prokeys[i], provalues[i]);
            }
            for (int i = 0; i < orderBys.length; i++) {
                order.append(orderBys[i], orders[i]);
            }
            for (int i = 0; i < includeFields.length; i++) {
                filter.append(includeFields[i], true);
            }
            MongoCollection coll = MongoTools.getCollection(collectionName);
            FindIterable iter = coll.find(doc).projection(filter).sort(order);
            MongoCursor cursor = iter.iterator();
            while (cursor.hasNext()) {
                Map m = (Map) cursor.next();
                m.remove("_id");
                list.add(m);
            }
            return list;
        }
    
        /**
         * 根据key/value获取bean.
         *
         * @param prokeys        key
         * @param provalues      value
         * @param collectionName 集合名
         * @param countField     累计字段
         * @param groupBy        分组字段
         */
        public List<Map<String, Object>> findAllByGroup(
                String[] prokeys, Object[] provalues, String collectionName,
                String countField, String groupBy) {
            Criteria criteria = new Criteria();
            Criteria[] criterias = new Criteria[prokeys.length];
            for (int i = 0; i < prokeys.length; i++) {
                criterias[i] = Criteria.where(prokeys[i].toString()).is(provalues[i]);
            }
            if (prokeys.length > 0) {
                criteria.andOperator(criterias);
            }
            GroupBy gb = new GroupBy(groupBy);
            if (countField != null && countField != "") {
                gb = gb.initialDocument("{count: 0}")
                        .reduceFunction("function (doc,pre){pre.count += doc." + countField + ";}");
            }
            GroupByResults groupByResults = mongoTemplate.group(criteria, collectionName, gb, Map.class);
            return (List<Map<String, Object>>) groupByResults.getRawResults().get("retval");
        }
    
        /**
         * 添加/更新符合条件的数据.
         *
         * @param querys         查询条件集合
         * @param updates        更新条件集合
         * @param collectionName 集合名
         */
        public void upsert(Map<String, Object> querys, Map<String, Object> updates,
                           String collectionName) {
            org.springframework.data.mongodb.core.query.Query query =
                    new org.springframework.data.mongodb.core.query.Query();
            for (Map.Entry e : querys.entrySet()) {
                query.addCriteria(Criteria.where(e.getKey().toString()).is(e.getValue()));
            }
            Update update = new Update();
            for (Map.Entry e : updates.entrySet()) {
                update.set(e.getKey().toString(), e.getValue());
            }
            // 新版本entityClass必传
            mongoTemplate.upsert(query, update, Map.class, collectionName);
        }
    
        /**
         * 更新指定key的数据.
         *
         * @param prokeys        待更新字段名
         * @param provalues      待更新字段值
         * @param collectionName 集合名
         */
        public void updateOne(String key, Integer id, String[] prokeys, Object[] provalues,
                              String collectionName) {
            org.springframework.data.mongodb.core.query.Query query =
                    new org.springframework.data.mongodb.core.query.Query();
            Criteria criteria = new Criteria(key);
            criteria.is(id);
            Update update = new Update();
            for (int i = 0; i < prokeys.length; i++) {
                update.set(prokeys[i].toString(), provalues[i]);
            }
            query.addCriteria(criteria);
            mongoTemplate.updateFirst(query, update, Map.class, collectionName);
        }
    
        /**
         * 插入map.
         *
         * @param collectionName 集合名
         */
        public void insert(Map<String, Object> map, String collectionName) throws IllegalAccessException {
            mongoTemplate.insert(map, collectionName);
        }
    
        /**
         * 插入bean.
         *
         * @param collectionName 集合名
         */
        public void insertMongo(Object object, String collectionName) {
            mongoTemplate.insert(object, collectionName);
        }
    
        /**
         * 删除指定key的数据.
         *
         * @param id             key值
         * @param collectionName 集合名
         */
        public void removeOne(String key, Object id, String collectionName, Class clazz) {
            org.springframework.data.mongodb.core.query.Query query =
                    new org.springframework.data.mongodb.core.query.Query();
            Criteria criteria = new Criteria(key);
            criteria.is(id);
            query.addCriteria(criteria);
            mongoTemplate.remove(query, clazz, collectionName);
        }
    
        /**
         * 重命名集合.
         */
        public void renameCollection(String oldCollection, String newCollection) {
            if (!mongoTemplate.collectionExists(oldCollection)) {
                return;
            }
            if (mongoTemplate.collectionExists(newCollection)) {
                mongoTemplate.dropCollection(newCollection);
            }
            MongoCollection mongoCollection = mongoTemplate.getCollection(oldCollection);
            mongoCollection
                    .renameCollection(new MongoNamespace(mongoTemplate.getDb().getName(), newCollection));
        }
    
        /**
         * 删除collection.
         */
        public void removeCollection(String collection) {
            if (!mongoTemplate.collectionExists(collection)) {
                return;
            } else {
                mongoTemplate.dropCollection(collection);
            }
        }
    }
    

    yml 文件配置:

    spring:
      data:
        mongodb:
          host: 127.0.0.1
          port: 27017
          database: testdb
          username: test
          password: password
    
  • 相关阅读:
    oracle与DB2
    oracle ORA-01427: 单行子查询返回多个行
    mysql开发总结
    mysql show profile基本详解
    mysql批量插入数据
    mysql索引详解
    mysql性能调优
    MySQL优化
    mysql主从调优
    mysql主从复制
  • 原文地址:https://www.cnblogs.com/weisenz/p/2454977.html
Copyright © 2020-2023  润新知