MongoDB Java Driver 是 MongoDB 的 Java 客户端开发包,即 Java 使用 MongoDB 的驱动包
一、准备工作
MongoDB安装教程:
Mongo-java-driver驱动包:https://github.com/mongodb/mongo-java-driver/releases
国内 mongodb-driver jar 下载地址:http://central.maven.org/maven2/org/mongodb/mongo-java-driver/
Maven坐标:http://mongodb.github.io/mongo-java-driver/3.5/driver/getting-started/installation/
<dependencies> <dependency> <groupId>org.mongodb</groupId> <artifactId>mongo-java-driver</artifactId> <version>3.5.0</version> </dependency> </dependencies>
Doc文档:http://mongodb.github.io/mongo-java-driver/3.5/javadoc/
在线查看源码:https://github.com/mongodb/mongo-java-driver
MongoDB对Java的相关支持、技术:http://mongodb.github.io/mongo-java-driver/
官方MongoDB Java驱动程序提供与MongoDB的同步和异步交互。
元素特征
BSON Lib
一个独立的BSON库,具有新的编解码器基础设施,可用于构建高性能编码器和解码器,无需中间地图实例。
MongoDB Driver
一个更新的Java驱动程序,其中包括传统的API以及符合新的跨驱动程序CRUD规范的新的通用MongoCollection界面。
MongoDB Async Driver
一种新的异步API,可以利用Netty或Java 7的AsynchronousSocketChannel快速和非阻塞IO。
Core Driver
MongoDB驱动程序和异步驱动程序都建立在新的核心库之上,任何人都可以使用它来构建替代或实验性高级API。
官方教程:http://mongodb.github.io/mongo-java-driver/3.5/driver/getting-started/quick-start/
二、连接数据库
将下载的驱动包,放在你的web项目中lib目录下
连接数据库,你需要指定数据库名称,如果指定的数据库不存在,mongo会自动创建数据库。
连接数据库的Java代码如下:
注意:以下所有代码中的close关闭连接方法为了阅读方便就放在了try中,这其实是不正规的,应该放在finally块中。
import com.mongodb.MongoClient; import com.mongodb.client.MongoDatabase; public class MongoDBJDBC { public static void main( String args[] ){ try{ // 连接到 mongodb 服务 MongoClient client = new MongoClient( "localhost" , 27017 ); // 连接到数据库对象 MongoDatabase db = client.getDatabase("chengxumiao"); System.out.println("数据库连接成功"); // 关闭链接,释放资源 client.close(); }catch(Exception e){ System.err.println( e.getClass().getName() + ": " + e.getMessage() ); } } }
本实例中 Mongo 数据库无需用户名密码验证。如果你的 Mongo 需要验证用户名及密码,可以使用以下代码:
import java.util.ArrayList; import java.util.List; import com.mongodb.MongoClient; import com.mongodb.MongoCredential; import com.mongodb.ServerAddress; import com.mongodb.client.MongoDatabase; public class MongoDBJDBC { public static void main(String[] args){ try { //连接到MongoDB服务 如果是远程连接可以替换“localhost”为服务器所在IP地址 //ServerAddress()两个参数分别为 服务器地址 和 端口 ServerAddress serverAddress = new ServerAddress("localhost",27017); List<ServerAddress> addrs = new ArrayList<ServerAddress>(); addrs.add(serverAddress); //MongoCredential.createScramSha1Credential()三个参数分别为 用户名 数据库名称 密码 MongoCredential credential = MongoCredential.createScramSha1Credential("username", "databaseName", "password".toCharArray()); List<MongoCredential> credentials = new ArrayList<MongoCredential>(); credentials.add(credential); //通过连接认证获取MongoDB连接 MongoClient mongoClient = new MongoClient(addrs,credentials); //连接到数据库 MongoDatabase mongoDatabase = mongoClient.getDatabase("databaseName"); System.out.println("Connect to database successfully"); } catch (Exception e) { System.err.println( e.getClass().getName() + ": " + e.getMessage() ); } } }
三、创建集合
我们可以使用 com.mongodb.client.MongoDatabase 类中的createCollection()来创建集合
public static void main(String[] args) { try{ // 连接到 mongodb 服务 MongoClient client = new MongoClient( "localhost" , 27017 ); // 连接到数据库 MongoDatabase mongoDatabase = client.getDatabase("chengxumiao"); System.out.println("创建chengxumiao数据库成功"); mongoDatabase.createCollection("student"); System.out.println("集合创建成功"); // 关闭连接 client.close(); }catch(Exception e){ System.err.println( e.getClass().getName() + ": " + e.getMessage() ); } }
创建成功如下图,一个chengxumiao数据库,和一个student集合(表)
四、获取集合(表)
我们可以使用com.mongodb.client.MongoDatabase类的 getCollection() 方法来获取一个集合
import com.mongodb.MongoClient; import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoDatabase; import org.bson.Document; public class Demo { public static void main(String[] args) { try{ // 连接到 mongodb 服务 MongoClient client = new MongoClient( "localhost" , 27017 ); // 连接到数据库 MongoDatabase mongoDatabase = client.getDatabase("chengxumiao"); System.out.println("连接 chengxumiao 数据库成功"); MongoCollection<Document> collection = mongoDatabase.getCollection("student"); System.out.println("集合 student 选择成功"); // 关闭连接 client.close(); }catch(Exception e){ System.err.println( e.getClass().getName() + ": " + e.getMessage() ); } } }
编译运行以上程序,输出结果如下:
Connect to database successfully 集合 test 选择成功
五、插入文档
我们可以使用com.mongodb.client.MongoCollection类的 insertMany() 方法来插入一个文档
import com.mongodb.MongoClient; import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoDatabase; import org.bson.Document; import java.util.ArrayList; import java.util.List; public class Demo { public static void main(String[] args) { try{ // 连接到 mongodb 服务 MongoClient client = new MongoClient( "localhost" , 27017 ); // 连接到数据库 MongoDatabase mongoDatabase = client.getDatabase("chengxumiao"); System.out.println("连接 chengxumiao 数据库成功"); MongoCollection<Document> collection = mongoDatabase.getCollection("student"); System.out.println("集合 student 选择成功"); //插入文档 /** * 1. 创建文档 org.bson.Document 参数为key-value的格式 * 2. 创建文档集合List<Document> * 3. 将文档集合插入数据库集合中 mongoCollection.insertMany(List<Document>) 插入单个文档可以用 mongoCollection.insertOne(Document) * */ Document document = new Document("title", "MongoDB"). append("description", "database"). append("likes", 100). append("by", "Anson"); List<Document> documents = new ArrayList<>(); documents.add(document); collection.insertMany(documents); System.out.println("文档插入成功"); // 关闭连接 client.close(); }catch(Exception e){ System.err.println( e.getClass().getName() + ": " + e.getMessage() ); } } }
创建成功如下图所示
_id为自动创建
创建成功后,可以多创建几条数据进行测试,比如我又新增一条数据如下
Document document = new Document("name", "Anson"). append("age", 24). append("sex", "男"). append("Job", "IT");
六、检索所有文档
我们可以使用 com.mongodb.client.MongoCollection 类中的 find() 方法来获取集合中的所有文档。
此方法返回一个游标,所以你需要遍历这个游标。
import com.mongodb.MongoClient; import com.mongodb.client.FindIterable; import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoCursor; import com.mongodb.client.MongoDatabase; import org.bson.Document; public class Demo { public static void main(String[] args) { try{ // 连接到 mongodb 服务 MongoClient client = new MongoClient( "localhost" , 27017 ); // 连接到数据库 MongoDatabase mongoDatabase = client.getDatabase("chengxumiao"); System.out.println("连接 chengxumiao 数据库成功"); MongoCollection<Document> collection = mongoDatabase.getCollection("student"); System.out.println("集合 student 选择成功"); //检索所有文档 /** * 1. 获取迭代器FindIterable<Document> * 2. 获取游标MongoCursor<Document> * 3. 通过游标遍历检索出的文档集合 * 4. 关闭游标 * */ FindIterable<Document> findIterable = collection.find(); // 建立游标 MongoCursor<Document> mongoCursor = findIterable.iterator(); while(mongoCursor.hasNext()){ System.out.println(mongoCursor.next()); } // 关闭游标 mongoCursor.close(); // 关闭连接 client.close(); }catch(Exception e){ System.err.println( e.getClass().getName() + ": " + e.getMessage() ); } } }
获取数据如下
连接 chengxumiao 数据库成功 集合 student 选择成功 Document{{_id=59a2a59b7ecf4e07f1e2d618, title=MongoDB, description=database, likes=100, by=Anson}} Document{{_id=59a2a6597ecf4e08028e7213, name=Anson, age=24, sex=男, Job=IT}}
七、(分页)获取多个文档
public static void main(String[] args) { try { // 连接到 mongodb 服务 MongoClient client = new MongoClient("localhost", 27017); // 连接到数据库 MongoDatabase mongoDatabase = client.getDatabase("chengxumiao"); System.out.println("连接 chengxumiao 数据库成功"); client.listDatabaseNames(); MongoCollection<Document> collection = mongoDatabase.getCollection("student"); System.out.println("集合 student 选择成功"); FindIterable<Document> findIterable = collection.find(); int pageNo = -1; int pageSize = 2; int record = pageNo * pageSize; findIterable.sort(new BasicDBObject("age", -1)); // 倒序排序 findIterable.limit(pageSize); //限制返回条数 findIterable.skip(record); //跳过前面指定数量的数据 // 建立游标 MongoCursor<Document> mongoCursor = findIterable.iterator(); while(mongoCursor.hasNext()){ System.out.println(mongoCursor.next()); } // 关闭游标 mongoCursor.close(); // 关闭连接 client.close(); } catch (Exception e) { System.err.println(e.getClass().getName() + ": " + e.getMessage()); } }
以上是使用limit+skip方式实现的分页,对于小的数据量还可以,如果查询的是很大的数据,那么使用这种方式就有些力不从心了。
经过网上各种查找资料,寻师问道的,发现了一种速度足以把skip+limit组合分页甩出几条街的方法。
思路: 条件查询+排序+限制返回记录。边查询,边排序,排序之后,抽取第一次分页中的最后一条记录,作为第二次分页的条件,进行条件查询,以此类推....
八、获取单个文档
使用Bson条件表达式来查询单个对象
public static void main(String[] args) { try{ // 连接到 mongodb 服务 MongoClient client = new MongoClient( "localhost" , 27017 ); // 连接到数据库 MongoDatabase mongoDatabase = client.getDatabase("chengxumiao"); System.out.println("连接 chengxumiao 数据库成功"); MongoCollection<Document> collection = mongoDatabase.getCollection("student"); System.out.println("集合 student 选择成功"); // 查询单个条件 Bson filter = new BasicDBObject("_id","59a2a6597ecf4e08028e7213"); // Bson filter = new BasicDBObject("_id", new ObjectId("59a2a6597ecf4e08028e7213")); FindIterable<Document> findIterable = collection.find(filter); // 建立游标 MongoCursor<Document> mongoCursor = findIterable.iterator(); while(mongoCursor.hasNext()){ System.out.println(mongoCursor.next()); } // 关闭游标 mongoCursor.close(); // 关闭连接 client.close(); }catch(Exception e){ System.err.println( e.getClass().getName() + ": " + e.getMessage() ); } }
以上代码根据_id方式不能正确来获取数据,这是因为id值为ObjectId类型,需要修改成如下代码才能正确获取到值。
Bson filter = new BasicDBObject("_id", new ObjectId("59a2a6597ecf4e08028e7213"));
如果使用的不是_id方式查询,比如使用name,就可以正常取到值
Bson filter = new BasicDBObject("name","Anson");
如果使用一些比较运算符,可以使用类似如下操作,年龄大于20岁的对象
map.put("age", new BasicDBObject("$gt", 20)); // age>20
多条件查询append方式
查询大于20岁,小于30岁的对象
map.put("age", new BasicDBObject("$gt", 20).append("$lte", 30));
多条件查询map方式
当然,除了上面的使用单个条件作为查询,也是可以使用多条件查询的,比如下面代码创建一个map对象就可以正确取到值
Map<String, Object> map = new HashMap<>(); map.put("name","Anson"); map.put("age",24); // 查询多条件 Bson filter = new BasicDBObject(map);
九、更新文档
你可以使用 com.mongodb.client.MongoCollection 类中的 updateMany() 方法来更新集合中的文档。
public class Demo { public static void main(String[] args) { try{ // 连接到 mongodb 服务 MongoClient client = new MongoClient( "localhost" , 27017 ); // 连接到数据库 MongoDatabase mongoDatabase = client.getDatabase("chengxumiao"); System.out.println("连接 chengxumiao 数据库成功"); MongoCollection<Document> collection = mongoDatabase.getCollection("student"); System.out.println("集合 student 选择成功"); //更新文档 将文档中likes=100的文档修改为likes=200 collection.updateMany(Filters.eq("likes", 100), new Document("$set",new Document("likes",200))); //检索所有文档 FindIterable<Document> findIterable = collection.find(); MongoCursor<Document> mongoCursor = findIterable.iterator(); while(mongoCursor.hasNext()){ System.out.println(mongoCursor.next()); } // 关闭游标 mongoCursor.close(); // 关闭连接 client.close(); }catch(Exception e){ System.err.println( e.getClass().getName() + ": " + e.getMessage() ); } } }
编译结果如下
连接 chengxumiao 数据库成功 集合 student 选择成功 Document{{_id=59a2a59b7ecf4e07f1e2d618, title=MongoDB, description=database, likes=200, by=Anson}} Document{{_id=59a2a6597ecf4e08028e7213, name=Anson, age=24, sex=男, Job=IT}}
十、删除文档
删除集合中的第一个文档:deleteOne(Bson查询条件)
删除所有符合条件的文档:deleteMany(Bson查询条件)
public static void main(String[] args) { try{ // 连接到 mongodb 服务 MongoClient client = new MongoClient( "localhost" , 27017 ); // 连接到数据库 MongoDatabase mongoDatabase = client.getDatabase("chengxumiao"); System.out.println("连接 chengxumiao 数据库成功"); MongoCollection<Document> collection = mongoDatabase.getCollection("student"); System.out.println("集合 student 选择成功"); //删除符合条件的第一个文档 collection.deleteOne(Filters.eq("likes", 200)); //删除所有符合条件的文档 // collection.deleteMany(Filters.eq("likes", 200)); //检索查看结果 FindIterable<Document> findIterable = collection.find(); // 创建游标 MongoCursor<Document> mongoCursor = findIterable.iterator(); while(mongoCursor.hasNext()){ System.out.println(mongoCursor.next()); } // 关闭游标 mongoCursor.close(); // 关闭连接 client.close(); }catch(Exception e){ System.err.println( e.getClass().getName() + ": " + e.getMessage() ); } }
十一、创建索引
MongoDB支持索引,并且给一个DBCollection添加索引非常简单,你只要指明需要创建索引的字段,然后指明其是升序(1)还是降序(-1)即可,比如在"age"上创建升序索引。
MongoCollection<Document> collection = mongoDatabase.getCollection("student"); System.out.println("集合 student 选择成功"); // 创建索引 String index_result = collection.createIndex(new BasicDBObject("age", 1)); System.out.println("创建索引成功:" + index_result); // 查询索引列表 ListIndexesIterable<Document> indexesIterable = collection.listIndexes(); // 建立游标 MongoCursor<Document> indexCursor = indexesIterable.iterator(); while (indexCursor.hasNext()) { System.out.println(indexCursor.next()); } // 关闭游标 indexCursor.close();
查询结果,创建数据库时,系统会默认建立一个_id的索引,上面代码中使用索引,又创建了一个age_1的索引,所以有两个。
创建索引成功:age_1 Document{{v=2, key=Document{{_id=1}}, name=_id_, ns=chengxumiao.student}} Document{{v=2, key=Document{{age=1}}, name=age_1, ns=chengxumiao.student}}
除了以上几个方法的示例入门,走进java操作mongodb的新大门,还有很多方法需要亲自去尝试。如下图,有时间可以练练手
其他关注点
有些时候你会看到类似于下面的代码片段,但是同样又能取到需要的执行结果
import com.mongodb.*; public class Demo { public static void main(String[] args) { try { // 连接到 mongodb 服务 MongoClient client = new MongoClient("localhost", 27017); // 连接到数据库 DB clientDB = client.getDB("chengxumiao"); System.out.println("连接 chengxumiao 数据库成功"); client.listDatabaseNames(); DBCollection collection = clientDB.getCollection("student"); System.out.println("集合 student 选择成功"); DBCursor dbCursor = collection.find(); // 倒序排序查询; int pageNo = 0; int pageSize = 5; int record = pageNo * pageSize; dbCursor.sort(new BasicDBObject("age", -1)); dbCursor.limit(5); //限制返回条数. dbCursor.skip(record); //跳过前面指定数量的数据 // 建立游标 while (dbCursor.hasNext()) { System.out.println(dbCursor.next()); } // 关闭游标 dbCursor.close(); // 关闭连接 client.close(); } catch (Exception e) { System.err.println(e.getClass().getName() + ": " + e.getMessage()); } } }
MongoDatabase 对应 DB
MongoCollection<Document> 对应 DBCollection
FindIterable<Document> 对应 DBCursor
仔细观察调用的源代码可以发现,其实以上的方法已经被逐步的淘汰掉了,我更推荐使用最新的方法。