MongoDB Java 开发全攻略(2025 最新版)
MongoDB 官方推荐的 Java 驱动是 MongoDB Java Driver(同步)与 MongoDB Reactive Streams Driver(响应式)。本文覆盖 同步、异步、响应式 三种编程模型,适用于 Spring Boot、微服务、批处理等场景。
一、驱动版本与兼容性
| 驱动类型 | 最新版本 | Maven 坐标 | 推荐场景 |
|---|---|---|---|
| 同步驱动 | 5.2.0 | org.mongodb:mongodb-driver-sync | 传统应用、Spring Boot |
| 异步驱动 | 5.2.0 | org.mongodb:mongodb-driver-async | 高并发、遗留系统 |
| 响应式驱动 | 5.2.0 | org.mongodb:mongodb-driver-reactivestreams | WebFlux、Vert.x |
| Spring Data MongoDB | 4.2.x (Spring Boot 3.x) | org.springframework.boot:spring-boot-starter-data-mongodb | Spring 生态 |
MongoDB 服务器版本:建议 ≥ 4.4(支持多文档 ACID 事务)
二、Maven 依赖(同步驱动)
<dependencies>
<!-- 同步驱动 -->
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-sync</artifactId>
<version>5.2.0</version>
</dependency>
<!-- 可选:BSON 编解码(POJO 支持) -->
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>bson</artifactId>
<version>5.2.0</version>
</dependency>
<!-- 日志(SLF4J) -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.13</version>
</dependency>
</dependencies>
三、连接 MongoDB(同步驱动)
1. 基础连接
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoDatabase;
public class MongoConnect {
public static void main(String[] args) {
// 1. 连接字符串(推荐)
String uri = "mongodb://localhost:27017/mydb";
try (MongoClient client = MongoClients.create(uri)) {
MongoDatabase db = client.getDatabase("mydb");
System.out.println("连接成功,数据库: " + db.getName());
}
}
}
2. 副本集 + 认证 + SSL
String uri = "mongodb://user:pass@host1:27017,host2:27017,host3:27017/mydb" +
"?replicaSet=rs0" +
"&authSource=admin" +
"&readPreference=secondaryPreferred" +
"&tls=true" +
"&tlsAllowInvalidCertificates=true";
MongoClient client = MongoClients.create(uri);
3. 连接池配置(生产推荐)
MongoClientSettings settings = MongoClientSettings.builder()
.applyConnectionString(new ConnectionString(uri))
.applyToConnectionPoolSettings(builder ->
builder.maxSize(50)
.minSize(10)
.maxWaitTime(120000, TimeUnit.MILLISECONDS)
.maxConnectionIdleTime(300000, TimeUnit.MILLISECONDS))
.applyToSocketSettings(builder ->
builder.connectTimeout(10000, TimeUnit.MILLISECONDS))
.build();
MongoClient client = MongoClients.create(settings);
四、CRUD 操作(同步)
1. 插入文档
MongoCollection<Document> coll = db.getCollection("users");
// 单条插入
Document doc = new Document("name", "Alice")
.append("age", 25)
.append("tags", Arrays.asList("dev", "java"));
coll.insertOne(doc);
// 批量插入
List<Document> docs = Arrays.asList(
new Document("name", "Bob").append("age", 30),
new Document("name", "Charlie").append("age", 35)
);
coll.insertMany(docs);
2. 查询
// 查找单个
Document user = coll.find(Filters.eq("name", "Alice")).first();
System.out.println(user.toJson());
// 条件查询
coll.find(Filters.and(
Filters.gte("age", 25),
Filters.lt("age", 40)
)).forEach(doc -> System.out.println(doc.toJson()));
// 分页 + 排序
coll.find()
.sort(Sorts.descending("age"))
.skip(10)
.limit(20)
.forEach(System.out::println);
3. 更新
// 更新单个
coll.updateOne(
Filters.eq("name", "Alice"),
Updates.combine(
Updates.set("age", 26),
Updates.addToSet("tags", "mongodb")
)
);
// 替换整个文档
Document newDoc = new Document("name", "Alice").append("status", "active");
coll.replaceOne(Filters.eq("_id", id), newDoc);
4. 删除
coll.deleteOne(Filters.eq("name", "Bob"));
coll.deleteMany(Filters.lt("age", 18));
五、POJO 编解码(推荐)
@Document(collection = "users")
public class User {
@BsonId
private ObjectId id;
private String name;
private Integer age;
private List<String> tags;
// getters and setters
}
// 注册 Codec
CodecRegistry pojoCodecRegistry = CodecRegistries.fromRegistries(
MongoClientSettings.getDefaultCodecRegistry(),
CodecRegistries.fromProviders(PojoCodecProvider.builder().automatic(true).build())
);
MongoClient client = MongoClients.create(
MongoClientSettings.builder()
.codecRegistry(pojoCodecRegistry)
.build()
);
MongoCollection<User> coll = db.getCollection("users", User.class);
coll.insertOne(new User("Alice", 25, Arrays.asList("java")));
User user = coll.find().first();
六、事务(ACID)
ClientSession session = client.startSession();
try {
session.startTransaction();
coll.insertOne(session, doc1);
coll.updateOne(session, filter, update);
session.commitTransaction();
} catch (Exception e) {
session.abortTransaction();
} finally {
session.close();
}
要求:副本集或分片集群 + WiredTiger
七、聚合(Aggregation)
coll.aggregate(Arrays.asList(
Aggregates.match(Filters.gte("age", 25)),
Aggregates.group("$name",
Accumulators.sum("total", 1),
Accumulators.avg("avgAge", "$age")
),
Aggregates.sort(Sorts.descending("total"))
)).forEach(doc -> System.out.println(doc.toJson()));
八、响应式编程(Reactive Streams)
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-reactivestreams</artifactId>
<version>5.2.0</version>
</dependency>
MongoClient client = MongoClients.create(uri);
MongoCollection<Document> coll = client.getDatabase("mydb").getCollection("users");
Publisher<Document> publisher = coll.find(Filters.eq("name", "Alice"));
publisher.subscribe(new Subscriber<Document>() {
private Subscription subscription;
@Override
public void onSubscribe(Subscription s) {
this.subscription = s;
s.request(1);
}
@Override
public void onNext(Document doc) {
System.out.println(doc.toJson());
subscription.request(1);
}
@Override
public void onError(Throwable t) { t.printStackTrace(); }
@Override
public void onComplete() { System.out.println("完成"); }
});
九、Spring Boot 集成(推荐)
1. 依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
2. 配置 application.yml
spring:
data:
mongodb:
uri: mongodb://user:pass@localhost:27017/mydb
# 或分开的配置
# host: localhost
# port: 27017
# database: mydb
# username: user
# password: pass
3. 实体与 Repository
@Document(collection = "users")
public class User {
@Id
private String id;
private String name;
private Integer age;
// getters and setters
}
@Repository
public interface UserRepository extends MongoRepository<User, String> {
List<User> findByAgeBetween(int min, int max);
Optional<User> findByName(String name);
}
4. 使用
@Service
public class UserService {
@Autowired
private UserRepository repo;
public User save(User user) {
return repo.save(user);
}
public List<User> findAdults() {
return repo.findByAgeBetween(18, 100);
}
}
十、性能优化建议
| 优化点 | 建议 |
|---|---|
| 连接池 | 合理设置 maxSize、minSize |
| 索引 | 使用 explain() 验证 |
| 批量操作 | insertMany、bulkWrite |
| 投影 | 只返回需要的字段 |
| 避免 N+1 | 使用聚合或 $lookup |
| 连接泄露 | 确保 close() 或使用 try-with-resources |
十一、常见问题排查
| 问题 | 原因 | 解决方案 |
|---|---|---|
MongoTimeoutException | 连接超时 | 检查网络、防火墙、连接字符串 |
DuplicateKeyException | 唯一索引冲突 | 检查 _id 或唯一字段 |
WriteConcernException | 写关注未满足 | 调整 w: 1 或检查副本集 |
POJO 编码失败 | 未注册 Codec | 添加 PojoCodecProvider |
十二、完整示例项目结构
src/
├── main/
│ ├── java/
│ │ ├── config/MongoConfig.java
│ │ ├── model/User.java
│ │ ├── repository/UserRepository.java
│ │ ├── service/UserService.java
│ │ └── MongoApp.java
│ └── resources/
│ └── application.yml
十三、学习资源
- 官方文档:MongoDB Java Driver
- Spring Data MongoDB:Reference
- 示例项目:GitHub – mongodb/mongo-java-driver
- 性能调优:Java Driver Performance
你想实现什么?
| 场景 | 我可以提供 |
|---|---|
| Spring Boot + 事务 | 完整模板 |
| 高并发写入 | 批量 + 连接池优化 |
| 响应式 WebFlux | Reactive Repository |
| 跨集合关联 | $lookup + 聚合 |
| 数据迁移 | mongodump + Java 导入 |
请告诉我:
- 使用框架(Spring Boot?纯驱动?)
- 业务模型(User/Order/Log?)
- 性能要求(QPS?延迟?)
我可以为你生成 可运行的完整项目代码!