目录
- 环境准备
- 安装 MongoDB
- 安装 Java 开发环境
- 添加 MongoDB Java 驱动依赖
- 连接 MongoDB
- 基本连接
- 连接字符串
- 连接池配置
- 核心概念与 API
MongoClientMongoDatabaseMongoCollectionDocumentFilters(查询条件)Projections(投影)
- CRUD 操作详解
- 创建 - 插入文档
- 读取 - 查询文档
- 更新 - 修改文档
- 删除 - 删除文档
- 高级特性
- 聚合
- 索引操作
- 事务
- 完整示例代码
- 最佳实践与注意事项
环境准备
a. 安装 MongoDB
如果您还没有安装 MongoDB,请从 MongoDB 官网 下载并安装,安装完成后,确保 MongoDB 服务正在运行。

b. 安装 Java 开发环境
确保您已安装 JDK (建议 JDK 8 或更高版本) 和 Maven (或其他构建工具如 Gradle)。
c. 添加 MongoDB Java 驱动依赖
这是最关键的一步,您需要在您的项目中添加 MongoDB 的 Java 驱动。
使用 Maven (pom.xml):
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-sync</artifactId>
<version>4.11.1</version> <!-- 请使用最新版本 -->
</dependency>
使用 Gradle (build.gradle):

implementation 'org.mongodb:mongodb-driver-sync:4.11.1' // 请使用最新版本
连接 MongoDB
a. 基本连接
连接到 MongoDB 的核心是 MongoClient,它代表一个到 MongoDB 部署的连接池。
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoDatabase;
// 1. 创建一个 MongoClient 实例
// 默认连接到 localhost:27017
MongoClient mongoClient = MongoClients.create();
// 2. 获取数据库 (如果数据库不存在,MongoDB 会在第一次插入数据时创建)
// 数据库是 "lazy" 的,此时不会连接
MongoDatabase database = mongoClient.getDatabase("myDatabase");
// 3. 获取集合 (类似于关系型数据库中的表)
// 集合也是 "lazy" 的
// com.mongodb.client.MongoCollection 是一个泛型类,需要指定文档类型
// 我们通常使用 com.mongodb.client.Document
import com.mongodb.client.MongoCollection;
import org.bson.Document;
MongoCollection<Document> collection = database.getCollection("users");
// ... 在这里执行操作 ...
// 4. 操作完成后,关闭客户端
mongoClient.close();
b. 连接字符串
在实际应用中,您通常需要连接到远程服务器或指定其他选项,这时应该使用连接字符串。
// 连接字符串格式: mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]] String connectionString = "mongodb://localhost:27017"; MongoClient mongoClient = MongoClients.create(connectionString); // 如果有认证 // String connectionString = "mongodb://user:password@localhost:27017/myDatabase";
c. 连接池配置
为了提高性能,MongoClient 内部默认使用了连接池,您可以通过 MongoClientSettings 进行更精细的配置。
import com.mongodb.MongoClientSettings;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;
// 配置连接池
MongoClientSettings settings = MongoClientSettings.builder()
.applyToClusterSettings(builder ->
builder.hosts(Arrays.asList(new ServerAddress("localhost", 27017))))
.applyToSocketSettings(builder ->
builder.connectTimeout(5, TimeUnit.SECONDS))
.applyToConnectionPoolSettings(builder ->
builder.maxConnectionIdleTime(60, TimeUnit.SECONDS))
.credential(MongoCredential.createCredential("myUser", "myDatabase", "myPassword".toCharArray()))
.build();
MongoClient mongoClient = MongoClients.create(settings);
核心概念与 API
MongoClient: 管理到 MongoDB 服务器的连接,它是线程安全的,通常在应用启动时创建一次,并在应用关闭时销毁。MongoDatabase: 代表一个数据库,它提供了对集合、运行命令等的访问。MongoCollection<TDocument>: 代表一个集合,它是执行所有 CRUD 操作的主要接口。Document: MongoDB 中的文档在 Java 驱动中用org.bson.Document类表示,它本质上是一个Map<String, Object>,可以方便地构建和解析 JSON 结构。Filters: 提供了一组静态工厂方法,用于构建查询过滤器 (Bson)。Filters.eq()(等于),Filters.gt()(大于),Filters.and()(与) 等。Projections: 提供了一组静态工厂方法,用于构建投影 (Bson),用于指定查询结果中应包含或排除哪些字段。
CRUD 操作详解
假设我们已经连接好,并获取了 collection 对象:
MongoCollection<Document> collection = database.getCollection("users");
a. 创建 - 插入文档
// 创建一个文档
Document doc1 = new Document("name", "Alice")
.append("age", 30)
.append("email", "alice@example.com")
.append("interests", Arrays.asList("reading", "hiking"));
// 插入一个文档
collection.insertOne(doc1);
// 创建另一个文档
Document doc2 = new Document("name", "Bob")
.append("age", 25)
.append("email", "bob@example.com");
// 插入多个文档
List<Document> documents = Arrays.asList(doc1, doc2);
collection.insertMany(documents);
b. 读取 - 查询文档
// 1. 查询所有文档
// find() 返回一个 FindIterable<Document>
// forEach() 是一个终端操作,会遍历所有结果
System.out.println("--- All Users ---");
collection.find().forEach(doc -> System.out.println(doc.toJson()));
// 2. 带条件的查询 (使用 Filters)
// 查找 age 等于 30 的用户
System.out.println("--- User with age 30 ---");
collection.find(Filters.eq("age", 30)).forEach(doc -> System.out.println(doc.toJson()));
// 3. 多条件查询 (AND)
// 查找 age 大于 28 且 name 是 Alice 的用户
System.out.println("--- User named Alice and older than 28 ---");
collection.find(Filters.and(Filters.gt("age", 28), Filters.eq("name", "Alice")))
.forEach(doc -> System.out.println(doc.toJson()));
// 4. 投影 (只返回特定字段)
// 查找所有用户,但只返回 name 和 age 字段
System.out.println--- All Users (name and age only) ---");
collection.find()
.projection(Projections.fields(Projections.include("name", age"), Projections.excludeId()))
.forEach(doc -> System.out.println(doc.toJson()));
// 5. 获取单个文档
// find() 返回一个迭代器,我们可以用 first() 获取第一个匹配的文档
Document firstUser = collection.find(Filters.eq("name", "Bob")).first();
if (firstUser != null) {
System.out.println("--- First User ---");
System.out.println(firstUser.toJson());
}
c. 更新 - 修改文档
// 1. 更新单个文档
// 更新第一个 name 为 "Alice" 的文档,将其 age 设置为 31
// $set 是一个更新操作符,用于设置字段值
collection.updateOne(
Filters.eq("name", "Alice"),
new Document("$set", new Document("age", 31))
);
// 2. 更新多个文档
// 将所有 age 小于 30 的用户的 age 加 1
collection.updateMany(
Filters.lt("age", 30),
new Document("$inc", new Document("age", 1))
);
// 3. 替换整个文档
// 用一个全新的文档替换第一个匹配的文档
Document newDoc = new Document("name", "Alice Smith")
.append("age", 31)
.append("email", "alice.smith@example.com")
.append("status", "active");
collection.replaceOne(
Filters.eq("name", "Alice"),
newDoc
);
d. 删除 - 删除文档
// 1. 删除单个文档
// 删除第一个 age 为 25 的文档
collection.deleteOne(Filters.eq("age", 25));
// 2. 删除多个文档
// 删除所有 age 小于 30 的文档
collection.deleteMany(Filters.lt("age", 30));
// 3. 删除集合中的所有文档
// collection.deleteMany(new Document()); // 匹配所有文档
// 4. 删除整个集合
// collection.drop();
高级特性
a. 聚合
聚合管道用于对数据进行复杂的处理,如分组、计算、过滤等。
// 示例:按年龄分组,并计算每个年龄的人数
List<Bson> pipeline = Arrays.asList(
// 第一阶段:按 age 字段分组
new Document("$group",
new Document("_id", "$age") // _id 是分组的字段
.append("count", new Document("$sum", 1)) // 为每个组计算总和,初始为1
),
// 第二阶段:按 _id (年龄) 升序排序
new Document("$sort",
new Document("_id", 1)
)
);
collection.aggregate(pipeline).forEach(doc -> System.out.println(doc.toJson()));
b. 索引操作
索引可以大大提高查询性能。
// 创建一个升序索引
collection.createIndex(new Document("name", 1));
// 创建一个复合索引
collection.createIndex(new Document("name", 1).append("age", -1));
// 查看集合的所有索引
collection.listIndexes().forEach(doc -> System.out.println(doc.toJson()));
c. 事务
MongoDB 4.0+ 支持多文档事务,事务用于将多个操作作为一个原子单元执行,所有操作都成功或都失败。
// 事务必须在同一个逻辑会话中运行
ClientSession session = mongoClient.startSession();
try {
session.startTransaction();
// 在事务中执行操作
collection.insertOne(session, new Document("account", "A").append("balance", 1000));
collection.insertOne(session, new Document("account", "B").append("balance", 500));
// 提交事务
session.commitTransaction();
System.out.println("Transaction committed successfully.");
} catch (Exception e) {
System.err.println("Transaction aborted: " + e.getMessage());
// 回滚事务
session.abortTransaction();
} finally {
session.close();
}
完整示例代码
这是一个将上述概念整合在一起的完整、可运行的示例。
import com.mongodb.client.*;
import com.mongodb.client.model.*;
import org.bson.Document;
import org.bson.conversions.Bson;
import java.util.Arrays;
public class MongoJavaExample {
public static void main(String[] args) {
// 1. 连接到 MongoDB
String uri = "mongodb://localhost:27017";
try (MongoClient mongoClient = MongoClients.create(uri)) {
MongoDatabase database = mongoClient.getDatabase("testDB");
MongoCollection<Document> collection = database.getCollection("students");
// 清空集合,以便每次运行结果一致
collection.deleteMany(new Document());
// 2. 创建 (插入)
System.out.println("--- Inserting Documents ---");
Document student1 = new Document("name", "John Doe")
.append("age", 22)
.append("major", "Computer Science")
.append("gpa", 3.8);
collection.insertOne(student1);
Document student2 = new Document("name", "Jane Smith")
.append("age", 21)
.append("major", "Mathematics")
.append("gpa", 3.9);
collection.insertOne(student2);
System.out.println("Inserted two students.");
// 3. 读取 (查询)
System.out.println("\n--- Reading Documents ---");
// 查询所有学生
System.out.println("All students:");
collection.find().forEach(doc -> System.out.println(doc.toJson()));
// 查询特定学生
System.out.println("\nStudent with name 'John Doe':");
collection.find(Filters.eq("name", "John Doe")).forEach(doc -> System.out.println(doc.toJson()));
// 投影查询
System.out.println("\nAll student names and majors:");
collection.find()
.projection(Projections.fields(Projections.include("name", "major"), Projections.excludeId()))
.forEach(doc -> System.out.println(doc.toJson()));
// 4. 更新
System.out.println("\n--- Updating Documents ---");
// 更新 John 的 GPA
collection.updateOne(
Filters.eq("name", "John Doe"),
Updates.set("gpa", 3.9)
);
System.out.println("Updated John's GPA.");
System.out.println("John's new info: " + collection.find(Filters.eq("name", "John Doe")).first().toJson());
// 5. 删除
System.out.println("\n--- Deleting Documents ---");
// 删除 Jane
collection.deleteOne(Filters.eq("name", "Jane Smith"));
System.out.println("Deleted Jane Smith.");
System.out.println("Remaining students:");
collection.find().forEach(doc -> System.out.println(doc.toJson()));
} catch (Exception e) {
e.printStackTrace();
}
}
}
最佳实践与注意事项
-
使用
try-with-resources:MongoClient实现了AutoCloseable接口,强烈建议使用try-with-resources语句来确保客户端在使用后被正确关闭,避免资源泄漏。try (MongoClient mongoClient = MongoClients.create(uri)) { // ... do work ... } // mongoClient.close() 会被自动调用 -
复用
MongoClient:MongoClient是线程安全的,并且内部管理着连接池,您应该在您的整个应用程序生命周期中只创建一个MongoClient实例,而不是为每个请求都创建一个新的。 -
处理
Bson类型: MongoDB 的文档可以包含各种 BSON 类型(日期、ObjectId、数组等),Java 驱动提供了BsonValue及其子类来处理这些类型,对于日期,可以使用new java.util.Date()。 -
异步驱动: 对于高并发、高性能的应用,可以考虑使用异步驱动
mongodb-driver-reactivestreams或mongodb-driver-async,它们基于 Project Reactor 或 RxJava,可以更高效地利用系统资源。 -
错误处理: 总是使用
try-catch块来处理可能发生的MongoException或其他运行时异常。 -
配置: 对于生产环境,务必配置好连接池、超时、读写偏好等参数,以适应您的负载和网络环境。
