Spring Boot从入门到精通-集成mongdb并实现自动分库分表

MongoDB是专为可扩展性,高性能和高可用性而设计的数据库。它可以从单服务器部署扩展到大型、复杂的多数据中心架构。利用内存计算的优势,MongoDB能够提供高性能的数据读写操作。

MongoDB使用文档的方式存储数据,而且非常容易进行分库分表的操作。在Spring Boot中集成mongdb非常简单,只需要在新建项目的时候勾选mongdb一项即可,使用起来也足够简单。但是由于使用时很简单也造成其不够灵活的特点,因此我们需要自己实现一个可以分库分表的mongdb操作代码。

  • 首先在pom.xml中引入mongdb依赖:
         <dependency>
            <groupId>org.mongodb</groupId>
            <artifactId>mongodb-driver</artifactId>
        </dependency>
  • mongdb是一种非关系型数据库,因此使用java连接的话也需要一些身份认证,在application.yml中加入配置信息:
xyh:
  mongodb:
      URI: mongodb://test:test123@127.0.0.1/
      dataBase: comment

注意:以上配置所用到的都是我们自己定义的变量名,127.0.0.1为本机地址,因此需要你额外安装mongdb

  • 有了配置之后就需要用代码去读取这些配置了,新建MongoDBManager.java类用于读取配置信息:
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

import com.mongodb.MongoClient;
import com.mongodb.MongoClientURI;

/**
 * MongoDB管理器
 */
@Component
public class MongoDBManager {
    /**
     * URI
     */
    @Value("${xyh.mongodb.URI}")
    private String uri;
    /**
     * URI
     */
    @Value("${xyh.mongodb.dataBase}")
    private String dataBase;

    /**
     * 获取 MongoClient 对象,可以只创建一个
     *
     * @return MongoClient对象
     */
    @Bean
    public MongoClient mongoClient() {
        System.out.println("\n\n\n\n\n" + uri + dataBase);

        return new MongoClient(new MongoClientURI(uri + dataBase));
    }


    public String getDataBase() {
        return dataBase;
    }

    public void setDataBase(String dataBase) {
        this.dataBase = dataBase;
    }
}

  • 接下来就是对mongdb的实际操作了,首先我们新建一个Writer.java类用于对mongdb进行写操作。相当于mysql中的insertupdate
package hys.mongodb.manage;

import com.alibaba.fastjson.JSONObject;
import com.mongodb.BasicDBObject;
import com.mongodb.MongoClient;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.model.UpdateOptions;
import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.result.UpdateResult;
import xyh.mongodb.utils.BsonTool;
import org.bson.Document;
import org.bson.conversions.Bson;
import org.springframework.stereotype.Repository;

import javax.annotation.Resource;
import java.util.UUID;

@Repository
public class Writer {

    @Resource
    private MongoClient mongoClient;

    /**
     * 数据存储
     *
     * @param dataBase 数据库
     * @param collect 业务代码,一个业务代码对应一个数据集
     * @param data 存储的数据
     */
    public void insert(String dataBase, String collect, JSONObject data) {
        JSONObject jso = new JSONObject();
        jso.putAll(data);
        if (jso.getString("id") == null) {
            String id = BsonTool.uuid();
            jso.put("id", id);
        }
        MongoCollection<Document> collection = getCollection(dataBase, collect);
        collection.insertOne(Document.parse(jso.toJSONString()));
    }

    /**
     *
     * @param dataBase 数据库
     * @param collect 集合
     * @param filter 过滤条件
     * @param update 更新对象
     */
    public boolean update(String dataBase, String collect, Bson filter, Bson update) {
        MongoCollection collection = getCollection(dataBase, collect);
        UpdateResult ur = collection.updateOne(filter, update);
        return ur.getModifiedCount() > 0;
    }

    /**
     * 当数据存在时更新数据,数据不存在时插入数据
     * @param dataBase
     * @param collect
     * @param filter
     * @param update
     * @return
     */
    public boolean upsert(String dataBase, String collect, Bson filter, Bson update) {
        MongoCollection collection = getCollection(dataBase, collect);
        //UpdateResult ur = collection.updateOne(filter, update);
        UpdateResult ur = collection.replaceOne(filter, update, new UpdateOptions().upsert(true));
        //UpdateResult ur = collection.updateOne(filter, update, new UpdateOptions().upsert(true));
        return ur.getModifiedCount() > 0;
    }

    /**
     * 删除文档
     * @param dataBase
     * @param collect
     * @param filter
     */
    public boolean delete(String dataBase, String collect, Bson filter) {
        MongoCollection collection = getCollection(dataBase, collect);
        DeleteResult dr = collection.deleteOne(filter);
        return dr.getDeletedCount() > 0;
    }

    private MongoCollection getCollection(String dataBase, String collect) {
        MongoDatabase db = mongoClient.getDatabase(dataBase);
        return db.getCollection(collect);
    }
}

Writer类中向外暴露了四个方法,基本上可以满足常规的增删改操作。

  • 然后我们新建一个Reader.java类用于对mongdb进行读操作,相当于mysql中的select
import com.alibaba.fastjson.JSONObject;
import com.mongodb.*;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import xyh.mongodb.beans.Comment;
import xyh.mongodb.beans.Pager;
import org.bson.Document;
import org.bson.conversions.Bson;
import org.springframework.stereotype.Repository;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

@Repository
public class Reader {
    @Resource
    private MongoClient mongoClient;

    /**
     * 数据存储
     *
     * @param dataBase 数据库
     * @param collect  业务代码,一个业务代码对应一个数据集
     */
    public <T> List<T> read(String dataBase, String collect, Bson cnd, Pager pager, Class<T> clazz) {
        final List<T> results = new ArrayList<>();
       Block<Document> iteratorResults = document -> {
            JSONObject jo = new JSONObject(document);
            results.add(JSONObject.toJavaObject(jo, clazz));
        };

        MongoDatabase db = mongoClient.getDatabase(dataBase);
        MongoCollection<Document> collection = db.getCollection(collect);

        if (pager == null) {
            //排序以及查询条件
            collection.find(cnd).sort(new BasicDBObject("insTime", 1))
                    .forEach(iteratorResults);
        } else {
            collection.find(cnd).sort(new BasicDBObject("insTime", 1))
                    .skip((pager.getPageNumber() - 1) * pager.getPageSize())
                    .limit(pager.getPageSize())
                    .forEach(iteratorResults);
        }

        return results;
    }

    /**
     * 返回总数
     *
     * @param dataBase 企业Id
     * @param collect  业务代码,一个业务代码对应一个数据集
     */
    public long count(String dataBase, String collect, Bson cnd) {
        MongoDatabase db = mongoClient.getDatabase(dataBase);
        MongoCollection<Document> collection = db.getCollection(collect);

        if (cnd == null) {
            return collection.count();
        } else {
            return collection.count(cnd);
        }
    }

    /**
     * 查询一个
     */
    public Document findOne(String dataBase, String collect, Bson bson) {
        return mongoClient.getDatabase(dataBase).getCollection(collect).find(bson).first();
    }
}

Reader类中向外暴露了三个方法,基本上可以满足常规的查询操作。
注意其中的两行代码:
MongoDatabase db = mongoClient.getDatabase(dataBase)
MongoCollection<Document> collection = db.getCollection(collect)
由于mongdb的结构是一个dataBase下有很多个collection,每个collection下又有很多个document,其中每一个document相当于一条数据。我们在查询mongdb的时候每次都是动态的去获取dataBase和collection,依靠这两句可以轻松的在mongdb中实现分库分表。
有了这两个操作mongdb基本的类之后,我们只需要调用这两个类中的相应方法就可以实现mongdb的增删改查了。
在mongdb中都是对Bson进行操作,而每个Bson的实现类又会去实现Map,所以mongdb中存储的都是类似于json格式的数据。
看下面的代码:

//调用reader类中的findOne方法,并将dataBase和collection传入(如果不想传dataBase和collection的话可以在初始化的时候写死),
//并且新建一个文档作为查询条件
reader.findOne(manager.getDataBase(), COMMENT + bizName, new Document("id", id));

看下面的代码:

// 新建一个文档用于更新
Document newDocument = new Document().append("$inc", new Document().append("lkNum", 1));
//新建一个文档用于查询
Document filter = new Document();
//查询条件
filter.put("id", id);
//调用刚刚writer类中的update方法,并将dataBase和collection传入,并将更新的文档和查询条件传入。
boolean updateCount = writer.update(manager.getDataBase(), COMMENT + bizName, filter, newDocument);

以上就是mongdb的增删改查操作。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,968评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,601评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,220评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,416评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,425评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,144评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,432评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,088评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,586评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,028评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,137评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,783评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,343评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,333评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,559评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,595评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,901评论 2 345

推荐阅读更多精彩内容

  • Java基础常见英语词汇(共70个)['ɔbdʒekt] ['ɔ:rientid]导向的 ...
    今夜子辰阅读 3,265评论 1 34
  • 一、MongoDB简介 1.概述 ​ MongoDB是一个基于分布式文件存储的数据库,由C++语言编写。旨在为WE...
    郑元吉阅读 974评论 0 2
  • MongoDB 一、安装 Windows下,下载安装包并安装 在安装盘的根目录下,新建data文件夹,里面新建lo...
    Plissmile阅读 5,395评论 0 4
  • 六张1001卡,讲一个故事,可以讲一个,可以每张卡一个,孩子讲孩子的,自己讲自己的。 在回家的路上看见两个大山,就...
    兮兮AX阅读 160评论 0 0
  • 淡淡柳眉愁,灼灼飞花梦。 遥怜香坠落,净土掩风流。 花下人独酌,人醉花亦醉。 花气袭人踞,怜取看花人。
    流湘遇阅读 265评论 0 0