操作场景
Java 是企业级应用开发的主流语言,MongoDB 官方 Java Driver 提供了同步和异步两种 API,并与 Spring Data MongoDB 深度集成。本文提供使用 Java 驱动连接云数据库 MongoDB 的完整示例,覆盖原生驱动和 Spring Boot 两种接入方式。
前提条件
已创建云数据库 MongoDB 实例,且实例状态为运行中。
已准备一台与 MongoDB 实例在同一 VPC 内的云服务器 CVM,且已安装 JDK 8 或以上版本。
开发环境已配置 Maven 或 Gradle 构建工具。
驱动版本
说明:
旧版
mongo-java-driver(3.x)已停止维护,请迁移至 4.x 版本。驱动 | 推荐版本 | 兼容 MongoDB 版本 | 说明 |
mongodb-driver-sync | 4.9或以上 | 4.0 - 8.0 | 官方同步驱动,适用于传统阻塞式编程 |
mongodb-driver-reactivestreams | 4.9或以上 | 4.0 - 8.0 | 官方响应式驱动,适用于异步非阻塞场景 |
注意事项
认证库配置:无论使用原生驱动还是 Spring Data MongoDB,都必须指定认证库为
admin。连接池管理:生产环境中,
MongoClient 实例应全局复用(单例模式),避免每次操作都创建新的连接。资源释放:使用完毕后,务必关闭
MongoClient。推荐使用 try-with-resources 语法自动关闭。异常处理:生产代码中应捕获
MongoException 及其子类,并进行相应的重试或告警处理。添加依赖
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'
方式一:原生 Java Driver 连接
以下示例演示使用 MongoDB Java Driver 连接云数据库 MongoDB,完成文档插入和查询操作。
package com.example.mongodb;import com.mongodb.ConnectionString;import com.mongodb.MongoClientSettings;import com.mongodb.client.*;import com.mongodb.client.model.Filters;import org.bson.Document;import java.util.concurrent.TimeUnit;public class MongoDBDemo {public static void main(String[] args) {// 连接 URI(请替换为您的实际连接信息)// 副本集连接串格式:// mongodb://mongouser:<password>@<IP1>:27017,<IP2>:27017,<IP3>:27017/admin?replicaSet=cmgo-xxxxxxxx_0String uri = "mongodb://mongouser:thepasswordA1@10.66.187.127:27017/admin";// 配置连接参数(包含连接池设置)MongoClientSettings settings = MongoClientSettings.builder().applyConnectionString(new ConnectionString(uri)).applyToConnectionPoolSettings(builder -> builder.maxSize(50) // 连接池上限.minSize(5) // 连接池下限.maxWaitTime(5, TimeUnit.SECONDS) // 等待可用连接的超时时间.maxConnectionIdleTime(60, TimeUnit.SECONDS)) // 空闲连接超时.applyToSocketSettings(builder -> builder.connectTimeout(10, TimeUnit.SECONDS) // 连接超时.readTimeout(30, TimeUnit.SECONDS)) // 读取超时.retryWrites(true) // 启用可重试写入.retryReads(true) // 启用可重试读取.build();// 创建客户端连接(使用 try-with-resources 自动关闭)try (MongoClient mongoClient = MongoClients.create(settings)) {// 选择数据库MongoDatabase database = mongoClient.getDatabase("mydb");// 获取集合MongoCollection<Document> collection = database.getCollection("users");// 插入文档Document doc = new Document("username", "jack").append("age", 31).append("email", "jack@example.com");collection.insertOne(doc);System.out.println("插入文档: " + doc.toJson());// 查询文档Document result = collection.find(Filters.eq("username", "jack")).first();if (result != null) {System.out.println("查询结果: " + result.toJson());}// 更新文档collection.updateOne(Filters.eq("username", "jack"),new Document("$set", new Document("age", 32)));System.out.println("更新完成");// 删除文档collection.deleteOne(Filters.eq("username", "jack"));System.out.println("删除完成");} catch (Exception e) {System.err.println("数据库操作失败: " + e.getMessage());e.printStackTrace();}}}
运行输出示例:
插入文档: {"username": "jack", "age": 31, "email": "jack@example.com", "_id": {"$oid": "6789abcdef1234567890abcd"}}查询结果: {"_id": {"$oid": "6789abcdef1234567890abcd"}, "username": "jack", "age": 31, "email": "jack@example.com"}更新完成删除完成
方式二:Spring Boot 集成
Spring Boot 通过 Spring Data MongoDB 提供了声明式的数据库操作支持,简化了开发流程。
添加依赖
Maven(pom.xml):
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-mongodb</artifactId></dependency>
配置连接信息
application.yml:
spring:data:mongodb:uri: mongodb://mongouser:thepasswordA1@10.66.187.127:27017/mydb?authSource=admin# 副本集连接串:# uri: mongodb://mongouser:thepasswordA1@IP1:27017,IP2:27017,IP3:27017/mydb?authSource=admin&replicaSet=cmgo-xxxxxxxx_0
说明:
authSource=admin 是必须的配置项,云数据库 MongoDB 统一使用 admin 库作为认证数据库。URI 中 /mydb 为业务数据库名称,与认证库 admin 是不同的概念。定义实体类
import org.springframework.data.annotation.Id;import org.springframework.data.mongodb.core.mapping.Document;@Document(collection = "users")public class User {@Idprivate String id;private String username;private Integer age;private String email;// 构造函数、getter 和 setter 省略}
定义 Repository
import org.springframework.data.mongodb.repository.MongoRepository;public interface UserRepository extends MongoRepository<User, String> {User findByUsername(String username);}
使用示例
import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.CommandLineRunner;import org.springframework.stereotype.Component;@Componentpublic class MongoDBRunner implements CommandLineRunner {@Autowiredprivate UserRepository userRepository;@Overridepublic void run(String... args) {// 插入文档User user = new User();user.setUsername("jack");user.setAge(31);user.setEmail("jack@example.com");userRepository.save(user);// 查询文档User found = userRepository.findByUsername("jack");System.out.println("查询结果: " + found);}}
常见问题
连接时抛出 "MongoSecurityException: Authentication failed"
异常堆栈示例:
com.mongodb.MongoSecurityException: Exception authenticating MongoCredential{mechanism=SCRAM-SHA-1, userName='mongouser', source='admin', ...}Caused by: com.mongodb.MongoCommandException: Command failed with error 18 (AuthenticationFailed)
请按以下步骤排查:
1. 确认 URI 中指定了认证库
admin:云数据库 MongoDB 的所有用户统一使用 admin 作为认证库。请确认 URI 格式正确:// 正确:URI 路径指向 adminString uri1 = "mongodb://mongouser:thepasswordA1@10.66.187.127:27017/admin";// 正确:连接业务库时通过 authSource 指定认证库String uri2 = "mongodb://mongouser:thepasswordA1@10.66.187.127:27017/mydb?authSource=admin";// 错误:连接业务库时未指定 authSource,驱动将默认以 mydb 库认证,导致认证失败String uri3 = "mongodb://mongouser:thepasswordA1@10.66.187.127:27017/mydb";
2. 确认密码中的特殊字符已进行 URL 编码:如密码包含
@、: 等特殊字符,需在 URI 中进行编码:import java.net.URLEncoder;import java.nio.charset.StandardCharsets;String password = URLEncoder.encode("pass@123", StandardCharsets.UTF_8);String uri = String.format("mongodb://mongouser:%s@10.66.187.127:27017/admin", password);
3. 确认用户名和密码正确:登录 MongoDB 控制台,在实例管理页面确认用户名信息。如忘记密码,可在控制台重置。
连接时抛出 "MongoTimeoutException: Timed out while waiting to connect"
异常信息示例:
com.mongodb.MongoTimeoutException: Timed out after 30000 ms while waiting to connect. Client view of cluster state is {type=UNKNOWN, servers=[...]
请按以下步骤排查:
1. 确认网络连通性:在 CVM 上执行以下命令,验证到 MongoDB 实例的网络是否可达:
telnet <MongoDB实例IP> 27017
输出
Connected 表示网络可达。输出
Connection timed out 表示网络不通,请确认 CVM 与 MongoDB 实例在同一 VPC 内,并检查安全组规则。2. 检查连接超时配置:确认
connectTimeoutMS 配置值合理。内网环境下,10秒(10000ms)足够:MongoClientSettings settings = MongoClientSettings.builder().applyConnectionString(new ConnectionString(uri)).applyToSocketSettings(builder -> builder.connectTimeout(10, TimeUnit.SECONDS)).build();
3. 步骤三:确认副本集名称正确:如使用副本集连接串,请确认
replicaSet 参数值与控制台实例详情页显示的副本集名称一致:mongodb://mongouser:thepasswordA1@IP1:27017,IP2:27017/admin?replicaSet=cmgo-xxxxxxxx_0
说明:
副本集名称通常为
cmgo-xxxxxxxx_0 格式,可在控制台实例详情页获取。运行一段时间后出现 "MongoSocketReadException: Prematurely reached end of stream"
异常信息示例:
com.mongodb.MongoSocketReadException: Prematurely reached end of stream
该异常通常由空闲连接被服务端主动断开引起。请检查连接池的空闲超时配置:
MongoClientSettings settings = MongoClientSettings.builder().applyConnectionString(new ConnectionString(uri)).applyToConnectionPoolSettings(builder -> builder.maxConnectionIdleTime(60, TimeUnit.SECONDS)) // 空闲连接 60 秒后自动关闭.build();
说明:
建议将
maxConnectionIdleTime 设置为60秒,避免长时间空闲的连接被服务端断开后仍被客户端复用。同时确保已开启 retryWrites(true) 和 retryReads(true),驱动会自动重试因连接断开而失败的操作。