1.Mongo和MongoClient的关系

MongoClient继承自Mongo,使用Mongo也可建立连接,但是需要使用与Mongo适应的MongoOptions,MongoURI等类型。

2.建立连接

在MongoDB Java Driver API中,要操作MongoDB的第一步和使用其他DB Java Driver类似,都需要首先和数据库建立连接。在MongoDBJava Driver API中,建立连接的类为com.mongodb.MongoClient.在讨论连接字符串等内容之前,我们来看看它最简单的使用方式:

  1. MongoClient client = new MongoClient();

一个构造函数不带任何参数的版本。使用这个构造函数连接到的是本地的MongoDB服务,即/127.0.0.1:27017,当然你如果改变了MongoDB服务的端口,那么这里显示的端口就是你的端口了。

可以通过以下单元测试代码进行验证:

  1. @Test
  2. public void testConstruactors() throws UnknownHostException {
  3. MongoClient client;
  4. client = new MongoClient();
  5. //也可指定连接的Host:
  6. //client = new MongoClient("127.0.0.1");
  7. assertEquals(new ServerAddress(), client.getAddress());
  8. client.close();
  9. }
3.设置连接的各项属性
和其他DB Java Driver的连接一样,MongoDB Java Driver的连接也提供了很多属性,来一起了解其中几个。要设置MongoClient有关连接的属性,需要用到com.mongodb.MongoClientOpations类。这个类包含了 MongoClient建立连接时,与连接相关的所有属性。该类提供了一Builder模式的方式创建并设置这些属性的值。
  1. MongoClientOptions customClientOptions = new MongoClientOptions.Builder().connectionsPerHost(100).build();

分析上面的代码,MongoClientOptions.Builder()得到的是一个MongoClientOptions的Builder,通过该Builder可以设置各种Options,例如connectionsPerHost(100),设置连接池中最大连接个数,需要注意的是,每个属性的设置方法的返回类型是一个Builder,这意味着可以采用类似下面的链式调用

  1. MongoClientOptions customClientOptions = new MongoClientOptions.Builder().connectionsPerHost(100).threadsAllowedToBlockForConnectionMultiplier(200).build();
最后,当我们将需要的各项值设定好后,就调用Builder的builder()方法,得到一个MongoClientOptions对象。问题来了,上面的代码只是为各项连接相关的属性赋值,那如何将这些值交给MongoClient,让它按照给出的属性值来建立连接呢?
 
答案就是MongoClient的构造函数,如下所示:
  1. MongoClientOptions customClientOptions = new MongoClientOptions.Builder().connectionsPerHost(50).maxWaitTime(2000).build();
  2. MongoOptions options = new MongoOptions(customClientOptions);
  3. client = new MongoClient("127.0.0.1", customClientOptions); // 每个MongoClient实例维护一个连接池
  4. assertEquals(new ServerAddress("127.0.0.1"), client.getAddress());
  5. assertEquals(options, client.getMongoOptions());
  6. client.close();

MongoOptions options=new MongoOptions(customClientOptions):这行代码并不影响MongoClientOptions的使用,只是展示如何获取到设置的MongoClientOptions。

此外,也可直接通过MongoClient.getMongoOptions()获取到MongoOptions后,进行设置,而不使用MongoClientOptions,如下

  1. MongoOptions mps = mongoClient.getMongoOptions();
  2. mps.setConnectionsPerHost(mongoDBConfig.getPoolSize());
  3. mps.setConnectTimeout(mongoDBConfig.getConnectTimeout());
  4. mps.setMaxWaitTime(mongoDBConfig.getMaxWaitTime());

通过两种方式的对比,我更喜欢MongoClientOptions,代码更加优雅。另外,即使没有设置MongoClientOptions,MongoClient也会有默认的设置。

4.使用连接字符串进行连接
上面的连接只是指定了连接到MongoDB的服务,但是具体连接到哪个数据库呢?使用什么样的登录名和密码呢?这个时候就用到连接字符串了,我们先解释下MongoDB的连接字符串,如下:
mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]

最简单的连接字符串就是:mongodb://127.0.0.1

当然,在真正在项目开发中,没人会这么用!!!!!!~~~回到主题,在MongoClient中,如何使用连接字符串进行连接呢?MongoDB Java Driver提供了一个 com.mongodb.MongoClientURI类型,使用方式如下:

  1. client = new MongoClient(new MongoClientURI("mongodb://kwiner:test123@127.0.0.1/test?authMechanism=MONGODB-CR&maxPoolSize=500"));
  2. client.close();

5.安全连接方式

MongoClient也提供了用户名和密码连接到指定数据库的方式,需要用到com.mongodb.MongoCredential,该类在mongo-java-driver的2.11.0版本中才开始提供,请注意!

  1. MongoClientOptions clientOptions=new MongoClientOptions.Builder().connectionsPerHost(poolSize).threadsAllowedToBlockForConnectionMultiplier(200).build();
  2. List<MongoCredential> lstCredentials = Arrays.asList(MongoCredential.createMongoCRCredential("admin", "myinfo", "123456".toCharArray()));
  3. client = new MongoClient(new ServerAddress("127.0.0.1"),lstCredentials, clientOptions);
  4. client.close();
  5.  
  6. 或者
  7.  
  8. MongoClientOptions mongoOptions=new MongoClientOptions.Builder().connectionsPerHost(poolSize).threadsAllowedToBlockForConnectionMultiplier(200).build();
  9. MongoClient mongoClient = new MongoClient(new ServerAddress(server, port), mongoOptions); // 每个MongoClient实例维护一个连接池
    try {
  10. db = mongoClient.getDatabase(database);
  11. collection = db.getCollection(table);
  12. catch (Exception e) {
  13.   mongoClient.close();
  14.   throw e;
  15. }
6.连接池
MongoClient本身就使用了连接池,如果我们使用了MongoClientOptions,则默认是100个连接
  1. MongoClientOptions.Builder builder = new MongoClientOptions.Builder();
  2. MongoClientOptions options = builder.build();
  3. assertEquals(100, options.getConnectionsPerHost());//最大连接数
  4. assertEquals(0, options.getMinConnectionsPerHost());//最小连接数
  5. assertEquals(0, options.getMaxConnectionIdleTime());//连接的最大闲置时间
  6. assertEquals(0, options.getMaxConnectionLifeTime());//连接的最大生存时间
  7. assertEquals(120000, options.getMaxWaitTime());//最大等待可用连接的时间
  8. assertEquals(10000, options.getConnectTimeout());//连接超时时间
  9.  
  10. MongoClient client = new MongoClient("127.0.0.1", customClientOptions);
  11. client.close();
其中, 闲置时间和生存时间为0,表示无限制。
MongoClient的close方法会关闭底层连接,MongoClient的实例将变得不可用,应该根据程序的需要,适当的调用该方法,释放资源。

7.连接副本集

使用MongoDB作为数据库,基本上都会使用副本集,在这个集里面,有primary节点,又有其他secondary节点,并使用了读写分离,这个时候,使用java连接MongoDB服务应该怎么做呢? 其实很简单,就是使用一个ServerAddress集合保存副本集中的所有节点,然后作为MongoClient的构造函数的参数,并使用ReadPreference设置读写策略,注意,ReadPreference的读写策略既可以在MongoClient上设置,作用与使用MongoClient连接的所有操作,也可以设置到每次具体的集合操作上,作用域该次操作。代码如下:

在MongoClient上设置读写策略:

  1. List<ServerAddress> addresses = new ArrayList<ServerAddress>();
  2. ServerAddress address1 = new ServerAddress("192.168.1.136" , 27017);
  3. ServerAddress address2 = new ServerAddress("192.168.1.137" , 27017);
  4. ServerAddress address3 = new ServerAddress("192.168.1.138" , 27017);
  5. addresses.add(address1);
  6. addresses.add(address2);
  7. addresses.add(address3);
  8.  
  9. mongoClient = new MongoClient(lstAddrs);
  10. mongoClient.setReadPreference(ReadPreference.primary());

在某次操作上设置读写策略:

  1. List<ServerAddress> addresses = new ArrayList<ServerAddress>();
  2. ServerAddress address1 = new ServerAddress("192.168.1.136" , 27017);
  3. ServerAddress address2 = new ServerAddress("192.168.1.137" , 27017);
  4. ServerAddress address3 = new ServerAddress("192.168.1.138" , 27017);
  5. addresses.add(address1);
  6. addresses.add(address2);
  7. addresses.add(address3);
  8.  
  9. MongoClient client = new MongoClient(addresses);
  10. DB db = client.getDB( "test" );
  11. DBCollection coll = db.getCollection( "test" );
  12.  
  13. BasicDBObject object = new BasicDBObject();
  14. object.append( "test2" , "testval2" );
  15.  
  16. //读操作从副本节点读取
  17. ReadPreference preference = ReadPreference.secondary();
  18. DBObject dbObject = coll.findOne(object, null , preference);
  19. System.out.println(dbObject);

8.mongo连接池属性设置

Mongo的实例其实就是一个数据库连接池,这个连接池里默认有10个链接。我们没有必要重新实现这个链接池,但是我们可以更改这个连接池的配置。因为Mongo的实例就是一个连接池,所以,项目中最好只存在一个Mongo的实例。

常见的配置参数:

connectionsPerHost:每个主机的连接数

threadsAllowedToBlockForConnectionMultiplier:线程队列数,它以上面connectionsPerHost值相乘的结果就是线程队列最大值。如果连接线程排满了队列就会抛出“Out of semaphores to get db”错误。

maxWaitTime:最大等待连接的线程阻塞时间

connectTimeout:连接超时的毫秒。0是默认和无限

socketTimeout:socket超时。0是默认和无限

autoConnectRetry:这个控制是否在一个连接时,系统会自动重试

还有许多配置,可以参见mongodb的API。

Java程序中与MongoDB建立连接~小记的更多相关文章

  1. 在java程序中使用JDBC连接mysql数据库

    在java程序中我们时常会用到数据库中的数据或操作数据库中的数据,如果java程序没有和我们得数据库连接,就不能实现在java程序中直接操作数据库.使用jdbc就能将java程序和数据库连起来,此时我 ...

  2. Derby安装,创建数据库,在Java程序中使用Derby

    1,下载并安装Derby: 下载地址:http://db.apache.org/derby /derby_downloads.html,下载最新版本. 我用的是10.5.3.0. 解压缩到任意文件夹, ...

  3. 2、Java应用中常见的JDBC连接字符串(SQLite、MySQL、Oracle、Sybase、SQLServer、DB2)

    2.Java应用中常见的JDBC连接字符串 Java应用中连接数据库是不可或缺的,于是便整理一些可能用到的JDBC的jar包及其相匹配的URL,以备日后查阅. 1)SQLite Class.forNa ...

  4. java程序中的经常出现的的异常处理课后总结

    一.JDK中常见的异常情况 1.常见异常总结图 2.java中异常分类 Throwable类有两个直接子类: (1)Exception:出现的问题是可以被捕获的 (2)Error:系统错误,通常由JV ...

  5. Linux上从Java程序中调用C函数

    原则上来说,"100%纯Java"的解决方法是最好的,但有些情况下必须使用本地方法.特别是在以下三种情况: 需要访问Java平台无法访问的系统特性和设备: 通过基准测试,发现Jav ...

  6. 在网页程序或Java程序中调用接口实现短信猫收发短信的解决方案

    方案特点: 在网页程序或Java程序中调用接口实现短信猫收发短信的解决方案,简化软件开发流程,减少各应用系统相同模块的重复开发工作,提高系统稳定性和可靠性. 基于HTTP协议的开发接口 使用特点在网页 ...

  7. 如何在java程序中调用linux命令或者shell脚本

    转自:http://blog.sina.com.cn/s/blog_6433391301019bpn.html 在java程序中如何调用linux的命令?如何调用shell脚本呢? 这里不得不提到ja ...

  8. [渣译文] 使用 MVC 5 的 EF6 Code First 入门 系列:MVC程序中实体框架的连接恢复和命令拦截

    这是微软官方教程Getting Started with Entity Framework 6 Code First using MVC 5 系列的翻译,这里是第四篇:MVC程序中实体框架的连接恢复和 ...

  9. Java程序中调用Python脚本的方法

    在程序开发中,有时候需要Java程序中调用相关Python脚本,以下内容记录了先关步骤和可能出现问题的解决办法. 1.在Eclipse中新建Maven工程: 2.pom.xml文件中添加如下依赖包之后 ...

随机推荐

  1. 时间处理之strtotime

    strtotime (PHP 4, PHP 5, PHP 7)strtotime - 将任何英文文本的日期时间描述解析为 Unix 时间戳说明 int strtotime ( string $time ...

  2. 论SNAPSHOT包的危害性

    先介绍一下背景:我们应用是一个标准的spring+webx工程,博主在一次项目发布前为了再次测试一下自己的代码,将分支部署到日常环境中,但是项目启动的时候报错: 第一眼看到这个堆栈后有点懵逼 第一是上 ...

  3. 关于js的parseInt方式在不同浏览器下的表现

    今天开发期间遇到个需求要把日期格式转换成毫秒数 日期为:2015-08-10 split之后使用parseInt将2015,08,10分别转化为数字格式. 但是使用parseInt('08')的时候却 ...

  4. C++ 头文件系列(ios)

    1 简介 我们都知道,平时常用的那些标准流,诸如iostream.ofstream.ifstream等等,其实都是对应的basic_XXX模版的实例类. 而这些basic_XXX类模版又都是继承自同一 ...

  5. 使用SBT编译Spark子项目

    前言 最近为了解决Spark2.1的Bug,对Spark的源码做了不少修改,需要对修改的代码做编译测试,如果编译整个Spark项目快的话,也得半小时左右,所以基本上是改了哪个子项目就单独对那个项目编译 ...

  6. TJOI2015 day1解题报告

    博客园的编辑器真的是太蛋疼了= =,想用tex然后上jpg又贴不了链接,真的很纠结啊= = T1:[TJOI2015]线性代数 描述:戳上面吧= = 首先这道题我觉得是这套题最漂亮的一道题了(虽然说学 ...

  7. BZOJ 1877: [SDOI2009]晨跑(费用流)

    看到要求两个量就下意识的想到了费用流= =,先把一个点拆成两个点就能够解决一个的只经过一次的限制 CODE: #include<cstdio>#include<iostream> ...

  8. BZOJ 3390: [Usaco2004 Dec]Bad Cowtractors牛的报复(最大生成树)

    这很明显就是最大生成树= = CODE: #include<cstdio>#include<iostream>#include<algorithm>#include ...

  9. BZOJ 3403: [Usaco2009 Open]Cow Line 直线上的牛(模拟)

    直接双端队列模拟,完了= = CODE: #include<cstdio>#include<algorithm>#include<iostream>#include ...

  10. .Net开源oss项目进度更新(含小程序接口)

    和大家分享下当前OSS开源项目的进度情况: 一. OSS.Common [开源中国] [github] 经过昨天的努力,oss.common项目初步完成了对.net standard的支持,迁移过程本 ...