Java 8 提供了很多工具,能让你连接 MongoDB,查询数据,甚至转换结果。
欢迎来到新的系列教程:使用 Java 8 学习 MongoDB。通过这份教程,希望大家对 Java 8 提供的大数据和新特性有基本的概念,同时我们会在本教程广泛使用这些新特性。
在这篇文章里面,我们将会学习:
下面是一些关于 MongoDB 的简单介绍。
MongoDB 是一种 NoSQL 类型的数据库。数据按照 BSON 格式进行存储,所有的数据按照键 / 值对(key/value)的方式进行存储。其中 key 表示属性,value 表示相对于 key 存储的属性值。
在 Mongo 里面,文档代表着一种能存储任意数量的键值对的数据结构。比如 "员工" 数据可以表示为一个文档,其中 name,address,age 和它们的值以键值对(key-value)的方式存储在该文档中。要注意的是,文档存储为一种二进制 JSON 格式,称为 BSON (Binary JSON)。
下面是一个文档的例子:
- {
- "_id": {
- "$oid" : "58eb8c2b1de2b36bfcc74326"
- },
- "name": "Shamik Mitra"
- }
在 Mongo 中,经常把具有相同数据结构的文档放入一个容器,并将其称为集合。可以把集合视为关系数据库中的表,每一行数据其实就对应着一个文档。所以我们可以认为 Employee 集合包含了多个 Employee 文档。不过要注意的是,这只是逻辑上面的一种理解。按照定义,一个集合可包含任意类型的文档 — 例如,一个集合能包含 Employee 文档以及 Car 文档。这些数据结构是没有约束的。
注意:在设计数据结构的时候,创建的集合最好与文档有着相似的结构。
这是 SQL 和 NoSQL 数据库之间的主要区别之一。对我而言,我不喜欢这些术语。我更倾向于使用关系数据库和非关系数据库来描述他们。使用 NoSQL,不需要任何预定义的模式 — 它能包含任何 BSON 格式的数据。具体来说,任何数据结构都适用于无模式数据库,因此它适用于存储非结构化的数据。
这使得开发者能更容易的进行开发,因为在关系型数据库中, 所有的数据都有一个固定的模式。比如一张员工表中有 name, age 和 address 字段,它存储的数据都保持着相同的数据结构。如果现在需要修改结构,比方说我们想要添加一个 gender 属性,则必须要改变表的模式以纳入新的属性。但是在 Mongo 中,因为它是模式自由的,所以这些都不需要,我们可将任何数据结构和任意属性的组合放在一起,可存储任意格式的数据。
注意:虽然 MongoDB 是模式自由的,但在设计的过程中,逻辑上我们把相同结构的文档放到一个集合中,所以会存在一个隐形的模式。
大数据的成功依赖于它的横向扩展能力。Mongo 作为大数据技术的一部分,当然也是支持的。通过横向扩展,MongoDB 能够将数据分发到多个节点上,每个节点都可以是低配的电脑,我们也可以轻松地添加和删除这些节点。所以当我们需要存储更多的数据时,可以添加新的节点而不影响现有的架构,然而在纵向扩展中(例如 RDBMS 使用的方式),我们则需要一台超级计算机,并且数据采用中央化存储的方式。
注意:在向多节点分发数据的时候,Mongo 有一定的容错机制。如果一个节点挂掉了之后,我们会使用其他的节点获取数据。当然,如果使用纵向扩展,因为数据是中央化存储,如果出现故障的话,我们会丢失所有的数据,这将会导致单点故障。
分片是 MongoDB 将庞大的数据块拆分成小的数据块的技术,之后,它会为每个块创建一份副本,然后这些块会被分发到多个节点中。当查询时,服务器通过元数据查询到数据所在的节点,然后从该节点返回查询结果。
进入 D:\InstalledApps\mongodb\bin
- cd D:\InstalledApps\mongodb\bin
- mongod.exe --dbpath D:\InstalledApps\mongodb\data
MongoDB Server 启动在 localhost:27017
我们将会使用 RoboMongo 作为 mongo 客户端。它有漂亮的图形化界面,所以我们可以轻松创建集合,并通过使用 RoboMongo GUI 添加文档。
RoboMongo 下载地址( 戳这里 ),解压 ZIP 文件后,双击 RoboMongo.exe 运行程序。它将启动 RoboMongo GUI 。
通过下面的步骤连接到 Mongo Server:
- {
- "name": "Shamik",
- "address": "1 Nivedita Lane",
- "age": 32
- }
点击 save ,这将在 Mongo Server 中插入文档。
这些操作其实也可以通过 Mongo 的控制台来完成。
上述的步骤完成后,就该写 Java 代码连接 MongoDB 数据库了。要用到的工具有:
首先,在 Eclipse 里创建一个名为 mongoExample 的 Maven 项目,并将 Java 编译器版本设置为 1.8。没有的话请去网上下载。
编写一个 pom.xml,如下所示:
- <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>
- 4.0.0
- </modelVersion>
- <groupId>
- com.example
- </groupId>
- <artifactId>
- mongoExample
- </artifactId>
- <version>
- 0.0.1-SNAPSHOT
- </version>
- <dependencies>
- <dependency>
- <groupId>
- org.mongodb
- </groupId>
- <artifactId>
- mongo-java-driver
- </artifactId>
- <version>
- 2.10.1
- </version>
- </dependency>
- </dependencies>
- </project>
可以看到我们用了 mongo-java-driver 这个库配合 Java 8 来连接 Mongo Server。
接下来,我们使用 Java 代码连接 Mongo Server。我们先写一个顶级 API 类,把连接 MongoDB Server 的操作抽象出来,并给调用者提供一些辅助方法:
- /**
- *
- */
- package com.example.config;
- import java.net.UnknownHostException;
- import java.util.
- function.Function;
- import com.mongodb.BasicDBObject;
- import com.mongodb.DB;
- import com.mongodb.DBCollection;
- import com.mongodb.DBCursor;
- import com.mongodb.MongoClient;
- /**
- * @author Shamik Mitra
- *
- */
- public class MongoContext {
- private static MongoContext ctx = new MongoContext();
- private MongoClient client;
- private DB db;
- private MongoContext() {
- try {
- init();
- } catch(Exception ex) {
- ex.printStackTrace();
- }
- }
- private void init() throws UnknownHostException {
- this.client = new MongoClient("localhost", 27017);
- }
- public static MongoContext get() {
- return ctx;
- }
- public MongoContext connectDb(String dbname) {
- if (db != null) {
- throw new RuntimeException("Already conected to " + db.getName() + "can't connect " + dbname);
- }
- this.db = client.getDB(dbname);
- System.out.println("DB Details :: " + db.getName());
- return ctx;
- }
- public < T,
- X > DBCursor findByKey(String collectionName, String key, T value, Function < T, X > convertDataType) {
- DBCollection collection = db.getCollection(collectionName);
- BasicDBObject searchQuery = new BasicDBObject();
- searchQuery.put(key, convertDataType.apply(value));
- System.out.println("search Query ::" + searchQuery);
- DBCursor cursor = collection.find(searchQuery);
- return cursor;
- }
- }
在代码中,我创建了一个单例对象 MongoContext。它的 init 方法会创建一个 MongoClient 类来连接 MongoDB。注意 MongoClient 类来自 Mongo Java Driver 这个库:
- this.client = new MongoClient("localhost" , 27017);
然后,我定义了静态的 get() 方法来返回类内部维护的 MongoContext 单例对象。
至此,成功建立了到 Mongo server 的连接。
下一步,指定需连接的数据库。我写了个 泛型方法 connectDb(String dbName),调用它就可以指定要连接到的数据库。注意这个方法返回的类型是类的单例对象 MongoContext 本身。这里我用了链式代码的风格( Fluent API )来写。
下一步,从数据库中查询到我们需要的文档。
为此,我写了个 泛型方法 :
- public < T,
- X > DBCursor findByKey(String collectionName, String key, T value, Function < T, X > convertDataType)
方法接受四个参数:
collectionName:代表要查询的集合名称,比如现在我们要查询的就是 Employee 集合。记住,可把集合看作关系型数据库里的表。
key:代表要从集合里查询的键,相当于在 SQL where 查询子句里指定的字段名。
value:代表键所对应的值,同样相当于 where 里给的值。
Function
然而,现在的情况是,我们并不知道调用者到底想查询什么键,于是就会比较麻烦。例如说,在 Employee 集合里,员工姓名这个键是 字符串类型 ,而年龄是 整型 。如果调用者想以姓名来查询,那对应的数据类型就得是字符串,同理查询年龄就得用整型。因此,我们得用一种特殊方法,能把提供的值转换成对应的类型。现在呢,我们用 Lambda 表达式来实现我们的需求。可以看一下 这篇文章 ,了解到底什么是 Lambda 表达式。
在方法内,我们得到了要查询的集合名称,然后创建了 BasicDataObject 类的一个对象 searchQuery 。随后,把参数里的键和值提供给对象来提供查询信息。最后,我们执行查询,并把得到的查询结果放进一个 DBCursor 对象里以进行维护。
来源: http://www.tuicool.com/articles/3I7Bze