“文档” 菜单
文档首页
/ / /
Java (Sync) 驱动程序

常见问题

在此页面上

如果在连接到 MongoDB 部署时遇到问题,请参阅《 连接故障排除指南》以了解可能的解决方案。

有两种类型的 MongoClient,因为我们希望为新用户提供更简洁的 API,避免因包含多个 CRUD API 而产生混乱。我们希望确保新的 CRUD API 以 Java 包结构提供,该结构能够很好地配合 Java 9 中引入的 Java 模块支持工作。

新应用程序通常使用com.mongodb.client.MongoClient接口,该接口支持:

  • 包含MongoClientSettingsConnectionString的配置。 您可以通过com.mongodb.client.MongoClients类中定义的工厂方法创建此接口的实例。

  • 使用MongoDatabase的 CRUD API,然后, MongoCollection

如果您需要支持旧版 API,请使用com.mongodb.MongoClient类,该类支持:

  • 包含MongoClientOptionsMongoClientURI的配置

  • 使用DB的 CRUD API,然后使用DBCollection 。 您可以通过getDB()方法访问此 API。

对于需要混合使用新旧版 API 的应用程序, com.mongodb.MongoClient还支持:

  • 配置为MongoClientSettingsConnectionString ,唯一的区别是您通过构造函数而不是工厂类创建实例。

  • 使用MongoDatabase的 CRUD API,然后使用MongoCollection 。 您可以通过getDatabase()方法访问此 API。

您可以使用MongoClientSettings类指定MongoClient实例的配置。 要构造MongoClientSettings实例,请使用MongoClientSettings.Builder类。

我们文档的以下部分展示了如何使用MongoClientSettings类执行不同的任务:

有关MongoClientSettings 类的更多信息,请参阅 MongoClientSettings 的 API 文档。

对于 MongoDB 拓扑结构中的每个服务器,每个 MongoClient 实例都有一个内置连接池。连接池按需打开套接字以支持多线程应用程序中的并发 MongoDB 操作。

每个连接池的最大大小由 maxPoolSize 选项设置,默认值为 100。如果某个服务器的在用连接数达到 maxPoolSize 值,则对该服务器的下一个请求将等待,直到出现可用连接。

每个MongoClient实例会为 MongoDB 拓扑结构中的每个服务器再打开两个套接字,用于监控服务器的状态。

例如,连接到 3 节点副本集的客户端会打开 6 个监控套接字。 它还根据需要打开任意数量的套接字以支持每台服务器上的应用程序线程,最多可达maxPoolSize的值。 如果maxPoolSize100且应用程序仅使用主节点(默认),则只有主节点连接池会增长,总连接数最多可为106 。 如果应用程序使用读取偏好(read preference)来查询从节点,则其池也会增长,总连接数可能为306

此外,连接池的速率受到限制,因此每个连接池在任何时候最多只能并行创建maxConnecting个连接。 任何其他线程在以下情况下都会停止等待:

  • 现有线程之一完成连接创建,或者现有连接重新签入池中。

  • 由于对创建连接的速率有限制,驱动程序重用现有连接的能力得到了提高。

您可以使用minPoolSize选项设置每个服务器的最小并发连接数,默认为0 。 连接池将使用此数量的套接字进行初始化。 如果套接字由于任何网络错误而关闭,导致套接字总数(包括使用中的和空闲的)下降到最小值以下,则会打开更多套接字,直到达到最小值。

您可以使用maxIdleTimeMS选项设置连接在被删除和替换之前在池中保持空闲状态的最大毫秒数,该选项默认为0 (无限制)。

以下 MongoClient 的默认配置适用于大多数应用程序:

MongoClient client = new MongoClient("<connection string>")

为每个进程创建一个客户端,并在所有操作中重复使用。为每个请求创建一个新客户端是个常见的错误,效率非常低。

要在一个进程中支持大量并发 MongoDB 操作,可以增加maxPoolSize 。 一旦池达到其最大大小,就会有其他线程等待套接字变为可用状态。

驱动程序不限制可以等待套接字变为可用状态的线程数,应用程序有责任在负载峰值期间将其池的大小限制为绑定队列。 线程等待waitQueueTimeoutMS选项中指定的时间,该时间默认为120000或 120 秒。

如果线程等待套接字的时间超过waitQueueTimeoutMS定义的时长,则会引发连接错误。 如果在负载峰值期间限制操作的持续时间比完成每个操作更重要,请使用此选项。

MongoClient.close() 被任何线程调用时,驱动程序会关闭所有闲置套接字,并关闭所有正在使用的套接字,因为这些套接字会返回到池中。

当 Java 运行时环境在运行时找不到类文件时,可能会遇到java.lang.NoClassDefFoundError异常。 当您尝试运行使用 MongoDB Java 驱动程序的应用程序代码时,必须在类路径中包含相应的驱动程序 JAR 文件。

如果在将 Java 驱动程序 JAR 文件添加到类路径后收到此错误,请检查环境中的以下项目:

  • JAR 文件存在于类路径指定的位置。

  • 类路径语法是正确的。

  • 如果在环境变量中定义类路径,Java 运行时环境将使用该变量。

  • 如果您使用依赖项经理,它不会报告任何无法解决的冲突。

提示

此错误包含包名称和类名称,可帮助您确定类路径中可能缺少哪个驱动程序 JAR。 要找到错误引用的驱动程序 JAR,请检查API 文档中的每个条目。

如果您在连接到 MongoDB 部署时指定了无效或格式不正确的档案,您的应用程序可能会抛出此异常。

如果在尝试连接到 MongoDB 部署时收到此错误,请检查代码中的以下项目:

  • 连接 URI 对应于正确的 MongoDB 部署。 要了解有关设置连接 URI 的更多信息,请参阅连接 URI。

  • 您指定的身份验证机制的档案是正确的。 要了解如何指定凭证,请参阅身份验证机制企业身份验证机制指南。

  • 您指定的身份验证数据库名称正确。 要了解如何为MongoDB 部署设置用户和角色,请参阅 MongoDB Server文档中的 管理用户和角色 。

如果您将格式不正确的文档传递给操作,并且您使用的是 v4.7 或更早版本的驱动程序,您的应用程序可能会抛出此异常。

注意

在驱动程序版本 v4.8 及更高版本中,此错误消息已替换为包含有关格式不正确内容的更具体详细信息的错误消息。

例如,当您调用更新操作并错误地省略更新操作符时,驱动程序会抛出此错误,如以下代码示例所示:

// incorrectly formatted update document
collection.updateOne(
new Document().append("name", "fizz"),
new Document().append("name", "buzz")
);

要避免此错误,请使用构建器类进行适当的操作。 该驱动程序提供了构建器类,以便为 MongoDB 操作创建语法正确的 BSON。 可以使用构建器类正确表达前面的示例,如以下代码示例所示:

// Builder class imports
import static com.mongodb.client.model.Filters.*;
import static com.mongodb.client.model.Updates.*;
// ...
collection.updateOne(eq("name", "fizz"), set("name", "buzz"));

要了解有关可用构建器类的更多信息,请参阅构建器文档。

如果您对MongoClient实例调用关闭与 MongoDB 连接的操作,则可能会遇到此异常。 在MongoClient上调用close()方法后,对该实例的任何进一步操作调用都会抛出此异常。

要避免此异常,请不要在对 MongoClient 实例调用close()的任何代码之后调用对实例的操作。

提示

在某些情况下,可能很难找到关闭MongoClient实例的代码。 要查找此异常的潜在来源,请搜索以下案例:

  • MongoClient实例上调用close()

  • MongoClient实例的操作调用超出了声明MongoClient的 try-with-resources 语句的范围

如果您的应用程序使用框架来托管MongoClient (例如 Spring Boot),请查看该框架的文档,找到托管连接行为的最佳实践。

要了解有关从 Spring Boot 访问 MongoDB 的更多信息,请参阅Spring Boot 和 MongoDB。

不会, PojoCodecProvider会自动生成 ObjectId。

是的。 有关示例,请参阅 我们的实现

是的,通过使用鉴别器。

鉴别器是标识特定文档模式的属性。 您可以将其用于继承,并在同一collection或父文档中存储多种类型的文档(如果嵌入了子文档)。

例如,如果您有在 Java 中扩展的Event类,例如MachineEventNetworkEvent ,则使用鉴别器识别PojoCodecProvider必须使用哪个类来序列化和反序列化文档。

有关更多信息,请参阅POJO 自定义指南。

是的,3.7 Java 驱动程序添加了对 JSR-310 InstantLocalDateLocalDateTime 的原生支持。

是的,您可以为此类构建自己的编解码器并将其添加到注册表中。

将编解码器添加到提供商列表中的第一个,默认编解码器注册表之前和PojoCodecProvider之前:

CodecRegistry registry = CodecRegistries.fromRegistries(
CodecRegistries.fromCodecs(
new MyDateAsStringCodec()),
MongoClientSettings.getDefaultCodecRegistry(),
fromProviders(pojoCodecProvider));

您可以将PojoCodecProvider配置为使用SET_PRIVATE_FIELDS_CONVENTION ,如果没有可用的公共 setter,则通过反射设置私有字段。

不可以。原生 POJO 编解码器假定每个字段的 getter/setter 具有相同的修饰符。

例如,以下方法会在编码期间引发异常:

private String getField();
public String setField(String x);

此异常意味着您必须为该类注册一个编解码器,因为目前没有。

没有注释。 我们建议在类中添加静态字符串,如下所示:

public class Person {
public static final String COLLECTION_NAME = "people";
}

以下代码段指定特定 POJO 类的collection名称:

database.getCollection(Person.COLLECTION_NAME, Person.class);

以下示例展示了如何使用旧版 API 和当前 API 连接到 MongoDB 实例。

假设我们要连接到一个仅包含此文档的集合:

{"_id": 1, "val": 1}

上述代码片段的输出如下所示:

{"_id": 1, "val": 1}

有关上一示例中使用的旧版类和方法的更多信息,请参阅以下 API 文档页面:

有关旧版 API 和当前 API 之间的差异列表,请参阅从旧版 API 迁移页面。

以下示例展示了如何使用旧版MongoClientOptionsMongoClientURI类来设置写关注(write concern):

有关上一示例中使用的旧版类和方法的更多信息,请参阅以下 API 文档页面:

有关旧版 API 和当前 API 之间的差异列表,请参阅从旧版 API 迁移页面。

如果您无法在此找到问题的答案,请尝试问题和帮助部分中列出的论坛和支持渠道。

← API 文档