MongoDB与Java(2)ITeye - 威尼斯人

MongoDB与Java(2)ITeye

2019年03月09日08时52分39秒 | 作者: 傲薇 | 标签: 办法,咱们,代码 | 浏览: 1717

咱们知道,MongoDB的三大根本元素是数据库,调集,文档,而这一章,咱们将学习怎样运用MongoDB Java Driver API来操作数据库。本章不会谈到一切的API,仅仅起一个抛砖引玉的办法。本章内容如下:

1. 数据库根本操作

2. 履行db.adminCommand指令

 

咱们仍是用代码来驱动解说,而不是解说来驱动代码。在本章中,乃至今后的章节中,都会沿袭运用单元测试代码的办法给出示例代码,所以,本章咱们会创立一个类型,该类型会作为今后单元测试的父类型。咱们把代码分红一小片一小片的来解说。

首要,咱们来看看该类型的字段:

 

public class BaseTest {
 /** 默许的衔接URI */
 public static final String DEFAULT_URI = "mongodb://localhost:27017";
 /** 保存MongoD衔接URI的体系特点key */
 public static final String MONGODB_URI_SYSTEM_PROPERTY_NAME = "org.mongodb.test.uri";
 /** 数据库名 */
 private static final String cleanupDB = "mongo-java-driver-test";
 private static MongoClientURI mongoClientURI;
 private static MongoClient staticMongoClient;
 public Mongo cleanupMongo = null;
 protected DBCollection collection;
}

 上面大部分都是咱们知道的类型,仅有的DBCollection表明数据库中的一个调集。后边会解说到。

接下来,看看获取衔接URI的代码:

 

/**
 * 获取MongoDB的衔接URI
 * @return
public static synchronized MongoClientURI getMongoClientURI() {
 if (mongoClientURI  null) {
 String mongoURIProperty = System.getProperty(
 MONGODB_URI_SYSTEM_PROPERTY_NAME);
 String mongoURIString = 
 (mongoURIProperty  null || mongoURIProperty.length()  0) ?
 DEFAULT_URI : mongoURIProperty;
 mongoClientURI = new MongoClientURI(mongoURIString);
 return mongoClientURI;
 }

  这段代码应该也十分简略了解,首要是从体系配置的特点中读取衔接字符串,假如不存在则运用默许的衔接字符串创立URI.

下面,咱们来看看树立衔接的代码:

/**
 * 树立衔接
@BeforeClass
public static void testCaseBeforeClass() {
 if (staticMongoClient  null) {
 try {
 staticMongoClient = new MongoClient(getMongoClientURI());
 staticMongoClient.dropDatabase(cleanupDB);
 Runtime.getRuntime().addShutdownHook(new Thread() {
 public void run() {
 if (staticMongoClient != null) {
 staticMongoClient.dropDatabase(cleanupDB);
 staticMongoClient.close();
 staticMongoClient = null;
 }});
 } catch (UnknownHostException e) {
 throw new RuntimeException(e);
 }

 这段代码也不难了解,留意staticMongoClient.dropDatabase用于删去指定称号的数据库。别的留意下Runtime部分的代码,该部分代表程序退出或许停止虚拟机时,会运转addShutdownHook中注册的线程,用于封闭衔接。

 

 

1.获取数据库

到此,根本代码完结,下面要看看供给给子类运用的办法。

/**
 * 获取MongoClient
 * @return
protected static MongoClient getMongoClient() {
 return staticMongoClient;
 * 获取数据库
 * @return
protected static DB getDatabase() {
 return staticMongoClient.getDB(cleanupDB);
}

 第一个办法没什么可讲的,第二个办法是要点,在MongoDB Java Driver API中,经过MongoClient的getDB办法,给出数据库称号,就能够得到一个DB目标,该目标就表明MongoDB中的一个数据库,这个目标是咱们操作调集的起点。

 

 

2.履行adminCommand指令

在MongoDB的shell中,供给了db.adminCommand来履行一些有关的指令。那么,在运用MongoDB Java Driver API时,怎样调用adminCommand来履行指令呢。其实十分简略,DB目标供给了一个command的办法,该办法最简略的版别就是承受一个String类型的参数,该参数表名了要履行的指令,command办法会回来一个com.mongodb.CommandResult目标,该目标实际上就是一个HashMap,里边保存了履行指令的成果。实际上就是将BSON格局的成果字符串映射到了HashMap中。

下面的代码,用于判别MongoDB是否大于给定的版别号。

 

/**
 * 判别MongoDB的版别号是否大于给定的版别号
 * @param version 版别号,有必要是1.1,2.1.3.1等的方式
 * @return
protected boolean serverIsAtLeastVersion(double version) {
 return serverIsAtLeastVersion(version, cleanupMongo);
 * 判别MongoDB的版别号是否大于给定的版别号
 * @param version 版别号,有必要是1.1,2.1.3.1等的方式
 * @param mongo 一个Mongo目标
 * @return
protected boolean serverIsAtLeastVersion(double version, Mongo mongo) {
 String serverVersion = 
 (String) mongo.getDB("admin").command("serverStatus").get("version");
 return Double.parseDouble(serverVersion.substring(0, 3)) = version;
}

 关键是代码mongo.getDB("admin").command("serverStatus").get("version"),为了履行调用adminCommand履行指令,咱们需求获取的数据库是admin.上面的代码相当于下面的MongoDB shell

 

 

db.serverStatus().version

 或

 

 

db.adminCommand({"serverStatus":1}).version

 接下来,咱们持续运用command来完成一些功用。看下面的代码:

 

 

/**
 * 判别是否为独自的效劳.即没有运用副本集或许分片
 * @param mongo the connection
 * @return true if connected to a standalone server
protected static boolean isStandalone(Mongo mongo) {
 return !isReplicaSet(mongo) !isSharded(mongo);
}

 在上面的办法中,别离调用了isReplicaSet和isShaeded两个办法。首要来看isReplicaSet办法,代码如下:

 

 

/**
 * 判别是否运用了副本集
 * @param mongo
 * @return
protected static boolean isReplicaSet(Mongo mongo) {
 return runIsMaster(mongo).get("setName") != null;
}

 在该办法中,最终是去调用runIsMaster办法,该办法会履行"ismaster"指令,获取主效劳相关的信息。而setName假如不为空,则表明运用了集群。咱们来看看runIsMaster的代码:

 

/**
 * 履行isMaster指令,获取master相关信息
 * @param mongo
 * @return
protected static CommandResult runIsMaster(Mongo mongo) {
 return mongo.getDB("admin").command(new BasicDBObject("ismaster", 1));
}

 BasicDBObject类型现在咱们不需求关怀,只需求知道它相似一个key/value,command办法需求该目标给出要履行的指令。上面的代码就相当于下面的MongoDB.shell

 

 

db.adminCommand({"ismaster":1})

 副本集是这样来判别,那么分片又是怎样判别的呢?这就是isSharded办法要做的工作。在MongoDB中,履行

db.adminCommand({"ismaster":1})

获取的BSON结构中,假如运用了分片,会有一个msg字段,该字段的值假如为“isdbgrid”则启用了分片。用java代码操作如下:

 

/**
 * 判别是否运用了分片
 * @param mongo
 * @return
protected static boolean isSharded(Mongo mongo) {
 CommandResult result = runIsMaster(mongo);
 Object msg = result.get("msg");
 return msg != null msg.equals("isdbgrid");
}

 

3.CommandResult

上面咱们现已看到了CommandResult的简略运用,本节中,咱们略微更进一步,假如回来的BSON成果中,有嵌套的文档,运用CommandResult怎样获取呢?例如下面的field2:

 

{
 field1:xxxx,
 field2:
 field2_1:xxxx,
 field2_2:xxxx,
 ....
}

接着1,2中的代码,咱们持续完善。假定咱们运用了副本集,我需求获取一切副本会集MongoDB节点信息,该怎样做呢?在MongoDB shell中,咱们能够运用:

 

db.adminCommand({"replSetGetStatus":1})

 在Java中怎样做呢?看下面的办法,该办法遍历副本会集的MongoDB节点,判别与给定的状况字符串是否持平,假如持平,就回来该MongoDB节点的hostName和port:

 

/**
 * 获取副本会集主机的hostname和port
 * @param mongo Mongo目标
 * @param stateStrToMatch 副本会集MongoDB节点的状况字符创(primary或许secondary)
 * @return 主机的hostname和port
@SuppressWarnings({"unchecked"})
protected String getMemberNameByState(Mongo mongo, String stateStrToMatch) {
 CommandResult replicaSetStatus = runReplicaSetStatusCommand(mongo);
 //遍历副本会集的成员
 for (final BasicDBObject member : (List BasicDBObject ) replicaSetStatus.get("members"){
 String hostnameAndPort = member.getString("name");
 if (!hostnameAndPort.contains(":"))
 hostnameAndPort = hostnameAndPort + ":27017";
 final String stateStr = member.getString("stateStr");
 if (stateStr.equalsIgnoreCase(stateStrToMatch))
 return hostnameAndPort;
 throw new IllegalStateException("No member found in state " + stateStrToMatch);
 }

 runReplicaSetStatusCommand办法下面解说,咱们现在只需求知道它相当于履行了db.adminCommand({"replSetGetStatus":1})指令。关键在于for循环,假如运用了副本集,回来的CommandResult中就会有一个members字段,该字段保存了一切副本集的信息,这些信息体现为一个个BasicDBObject目标。在for循环中,咱们遍历每一个副本集成员,留意if (!hostnameAndPort.contains(":")),副本集的"name"字段保存了副本集的hostname和port,方式为host:port,该判别表明的是,假如副本会集的成员的"name"值没有":",则运用的是默许的端口27017.别的,"stateStr"则是副本集的状况,一般是PRIMARY,SECONDARY等值。

接下来时runReplicaSetStatusCommand办法,在解说该办法之前,咱们要烦琐下db.adminCommand({"replSetGetStatus":1})指令,假如没有运用副本集,则该指令回来的BSON回来BSON如下:

 

{
 "ok" : 0,
 "errmsg" : "not running with replSet"
}

 

runReplicaSetStatusCommand就利用了errmsg来决议回来值,代码如下:

protected static CommandResult runReplicaSetStatusCommand(final Mongo mongo) {
 final CommandResult result = mongo.getDB("admin").command(
 new BasicDBObject("replSetGetStatus", 1));
 String errorMsg = result.getErrorMessage();
 if (errorMsg != null errorMsg.indexOf("replSet") != -1) {
 System.err.println(" SecondaryReadTest: This is not a replica set - not testing secondary reads");
 return null;
 return result;
 }

 

最终是调用getMemberNameByState的两个get办法

/**
 * 获取primary的hostname和port
 * @param mongo
 * @return
@SuppressWarnings({"unchecked"})
protected String getPrimaryAsString(Mongo mongo) {
 return getMemberNameByState(mongo, "primary");
 * 获取secondary的hostname和port
 * @param mongo
 * @return
@SuppressWarnings({"unchecked"})
protected String getASecondaryAsString(Mongo mongo) {
 return getMemberNameByState(mongo, "secondary");
}

 最终看一个办法,这儿不做解说,我们自己看看它是做什么的:

@SuppressWarnings("unchecked")
protected int getReplicaSetSize(Mongo mongo) {
 int size = 0;
 CommandResult replicaSetStatus = runReplicaSetStatusCommand(mongo);
 for (final BasicDBObject member : 
 (List BasicDBObject ) replicaSetStatus.get("members")) {
 final String stateStr = member.getString("stateStr");
 if (stateStr.equals("PRIMARY") || stateStr.equals("SECONDARY"))
 size++;
 return size;
 }

 

 

 

版权声明
本文来源于网络,版权归原作者所有,其内容与观点不代表威尼斯人立场。转载文章仅为传播更有价值的信息,如采编人员采编有误或者版权原因,请与我们联系,我们核实后立即修改或删除。

猜您喜欢的文章

阅读排行

  • 1

    MongoDB与Java(2)ITeye

    办法,咱们,代码
  • 2
  • 3

    Java多线程编程ITeye

    线程,音讯,出产
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

    FileDowloadITeye

    途径,获取,绝对