MongoDB Java

MongoDB Java 开发全攻略(2025 最新版)

MongoDB 官方推荐的 Java 驱动是 MongoDB Java Driver(同步)与 MongoDB Reactive Streams Driver(响应式)。本文覆盖 同步、异步、响应式 三种编程模型,适用于 Spring Boot、微服务、批处理等场景。


一、驱动版本与兼容性

驱动类型最新版本Maven 坐标推荐场景
同步驱动5.2.0org.mongodb:mongodb-driver-sync传统应用、Spring Boot
异步驱动5.2.0org.mongodb:mongodb-driver-async高并发、遗留系统
响应式驱动5.2.0org.mongodb:mongodb-driver-reactivestreamsWebFlux、Vert.x
Spring Data MongoDB4.2.x (Spring Boot 3.x)org.springframework.boot:spring-boot-starter-data-mongodbSpring 生态

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);
    }
}

十、性能优化建议

优化点建议
连接池合理设置 maxSizeminSize
索引使用 explain() 验证
批量操作insertManybulkWrite
投影只返回需要的字段
避免 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

十三、学习资源


你想实现什么?

场景我可以提供
Spring Boot + 事务完整模板
高并发写入批量 + 连接池优化
响应式 WebFluxReactive Repository
跨集合关联$lookup + 聚合
数据迁移mongodump + Java 导入

请告诉我:

  1. 使用框架(Spring Boot?纯驱动?)
  2. 业务模型(User/Order/Log?)
  3. 性能要求(QPS?延迟?)

我可以为你生成 可运行的完整项目代码

文章已创建 2371

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部