模板 API
MongoTemplate 及其对应的响应式类 ReactiveMongoTemplate,位于 org.springframework.data.mongodb.core 包中,是 Spring 对 MongoDB 支持的核心类,提供了丰富的功能集来与数据库进行交互。该模板提供了便捷的操作来创建、更新、删除和查询 MongoDB 文档,并在领域对象与 MongoDB 文档之间提供了映射功能。
一旦配置完成,MongoTemplate 是线程安全的,并且可以在多个实例中重复使用。
便捷方法
MongoTemplate 类实现了 MongoOperations 接口。MongoOperations 上的方法尽可能以 MongoDB 驱动程序的 Collection 对象上的方法命名,以便使熟悉驱动程序 API 的现有 MongoDB 开发人员能够轻松上手。例如,你可以找到诸如 find、findAndModify、findAndReplace、findOne、insert、remove、save、update 和 updateMulti 等方法。设计目标是尽可能地简化从基础 MongoDB 驱动程序到 MongoOperations 的过渡。这两个 API 之间的主要区别在于,MongoOperations 可以传递领域对象而不是 Document。此外,MongoOperations 为 Query、Criteria 和 Update 操作提供了流畅的 API,而不是通过填充 Document 来指定这些操作的参数。
引用 MongoTemplate 实例上操作的首选方式是通过其接口 MongoOperations。
执行回调
MongoTemplate 提供了许多便捷方法,帮助你轻松执行常见任务。然而,如果你需要直接访问 MongoDB 驱动程序 API,你可以使用多个 Execute 回调方法之一。execute 回调方法会为你提供对 MongoCollection 或 MongoDatabase 对象的引用。
- 
<T> Texecute(Class<?> entityClass, CollectionCallback<T> action): 为指定类的实体集合运行给定的CollectionCallback。
- 
<T> Texecute(String collectionName, CollectionCallback<T> action): 在给定名称的集合上运行给定的CollectionCallback。
- 
<T> Texecute(DbCallback<T> action): 运行DbCallback,必要时转换任何异常。Spring Data MongoDB 提供了对 MongoDB 2.2 版本中引入的聚合框架的支持。
- 
<T> Texecute(String collectionName, DbCallback<T> action): 在给定名称的集合上运行DbCallback,必要时转换任何异常。
- 
<T> TexecuteInSession(DbCallback<T> action): 在同一个数据库连接中运行给定的DbCallback,以确保在写入频繁的环境中读取你写入的数据时的一致性。
以下示例使用 CollectionCallback 返回有关索引的信息:
- Imperative
- Reactive
boolean hasIndex = template.execute("geolocation", collection ->
    Streamable.of(collection.listIndexes(org.bson.Document.class))
        .stream()
        .map(document -> document.get("name"))
        .anyMatch("location_2d"::equals)
);
Mono<Boolean> hasIndex = template.execute("geolocation", collection ->
    Flux.from(collection.listIndexes(org.bson.Document.class))
        .map(document -> document.get("name"))
        .filterWhen(name -> Mono.just("location_2d".equals(name)))
        .map(it -> Boolean.TRUE)
        .single(Boolean.FALSE)
    ).next();
流畅 API
作为与 MongoDB 进行更底层交互的核心组件,MongoTemplate 提供了广泛的方法,涵盖了从集合创建、索引创建和 CRUD 操作到更高级功能(如 Map-Reduce 和聚合)的需求。你可以找到每个方法的多个重载版本,其中大多数涵盖了 API 中的可选或可为空的部分。
FluentMongoOperations 为 MongoOperations 的常见方法提供了一个更为简洁的接口,并提供了一个更具可读性和流畅性的 API。入口点(insert(...)、find(...)、update(...) 等)遵循基于要执行的操作的自然命名模式。从入口点开始,API 设计为仅提供上下文相关的方法,这些方法最终会调用实际的 MongoOperations 对应方法——在以下示例中,即为 all 方法:
命令式
List<Jedi> all = template.query(SWCharacter.class) 1
  .inCollection("star-wars") 2
  .as(Jedi.class) 3
  .matching(query(where("jedi").is(true))) 4
  .all();
- 用于映射查询中字段的类型。 
- 如果未在域类型上定义,则使用的集合名称。 
- 如果不使用原始域类型,则使用的结果类型。 
- 查找查询。 
响应式
Flux<Jedi> all = template.query(SWCharacter.class)
  .inCollection("star-wars")
  .as(Jedi.class)
  .matching(query(where("jedi").is(true)))
  .all();
使用投影允许 MongoTemplate 通过将实际响应限制为投影目标类型所需的字段来优化结果映射。只要 Query 本身不包含任何字段限制,并且目标类型是封闭接口或 DTO 投影,这一点就适用。
投影(Projections)不能应用于 DBRefs。
你可以通过终止方法在检索单个实体和检索多个实体(作为 List 或 Stream)之间切换,这些方法包括:first()、one()、all() 或 stream()。
在使用 near(NearQuery) 编写地理空间查询时,终止方法的数量会被修改,只包含在 MongoDB 中运行 geoNear 命令时有效的方法(将实体作为 GeoResults 中的 GeoResult 获取),如下例所示:
- Imperative
- Reactive
GeoResults<Jedi> results = template.query(SWCharacter.class)
  .as(Jedi.class)
  .near(alderaan) // NearQuery.near(-73.9667, 40.78).maxDis…
  .all();
Flux<GeoResult<Jedi>> results = template.query(SWCharacter.class)
  .as(Jedi.class)
  .near(alderaan) // NearQuery.near(-73.9667, 40.78).maxDis…
  .all();
异常翻译
Spring 框架为多种数据库和映射技术提供了异常转换机制。这一传统上适用于 JDBC 和 JPA。Spring 对 MongoDB 的支持通过提供 org.springframework.dao.support.PersistenceExceptionTranslator 接口的实现,将此功能扩展到了 MongoDB 数据库。
将异常映射到 Spring 的一致的数据访问异常层次结构背后的动机是,您能够编写可移植且描述性强的异常处理代码,而无需依赖于 MongoDB 的错误代码。Spring 的所有数据访问异常都继承自根类 DataAccessException,因此您可以确保在一个 try-catch 块中捕获所有与数据库相关的异常。需要注意的是,并非所有由 MongoDB 驱动程序抛出的异常都继承自 MongoException 类。内部异常和消息会被保留,以确保不会丢失任何信息。
由 MongoExceptionTranslator 执行的一些映射包括将 com.mongodb.Network 映射到 DataAccessResourceFailureException,以及将 MongoException 错误代码 1003、12001、12010、12011 和 12012 映射到 InvalidDataAccessApiUsageException。有关映射的更多详细信息,请查看其实现。
异常转换可以通过在 MongoDatabaseFactory 或其响应式变体上设置自定义的 MongoExceptionTranslator 来配置。你可能还希望在相应的 MongoClientFactoryBean 上设置异常转换器。
示例 1. 配置 MongoExceptionTranslator
ConnectionString uri = new ConnectionString("mongodb://username:password@localhost/database");
SimpleMongoClientDatabaseFactory mongoDbFactory = new SimpleMongoClientDatabaseFactory(uri);
mongoDbFactory.setExceptionTranslator(myCustomExceptionTranslator);
自定义异常的一个动机可能是 MongoDB 在事务中的行为,其中某些故障(例如写入冲突)可能会变为暂时性的,而重试可能会导致操作成功。在这种情况下,你可以用特定的 MongoDB 标签包装异常,并应用不同的异常转换策略。
域类型映射
MongoDB 文档与领域类之间的映射是通过委托给 MongoConverter 接口的实现来完成的。Spring 提供了 MappingMongoConverter,但您也可以编写自己的转换器。虽然 MappingMongoConverter 可以使用额外的元数据来指定对象到文档的映射,但它也可以通过使用一些约定来转换不包含额外元数据的对象,这些约定用于 ID 和集合名称的映射。这些约定以及映射注解的使用在 映射 章节中有详细说明。
章节摘要
📄️ 配置
你可以使用以下配置来创建并注册 MongoTemplate 的实例,如下例所示:
📄️ 索引与集合管理
MongoTemplate 和 ReactiveMongoTemplate 提供了管理索引和集合的方法。这些方法被收集到一个辅助接口中,分别称为 IndexOperations 和 ReactiveIndexOperations。你可以通过调用 indexOps 方法并传入集合名称或实体类的 java.lang.Class(集合名称从 .class 中派生,通过名称或注解元数据)来访问这些操作。
📄️ 保存、更新和删除文档
MongoTemplate / ReactiveMongoTemplate 允许你保存、更新和删除你的领域对象,并将这些对象映射到存储在 MongoDB 中的文档。命令式和响应式 API 的签名基本相同,仅在返回类型上有所不同。同步 API 使用 void、单个 Object 和 List,而响应式 API 则由 Mono\<Void>、Mono\<Object> 和 Flux 组成。
📄️ 查询文档
你可以使用 Query 和 Criteria 类来表达你的查询。它们的方法名称与原生 MongoDB 操作符名称相对应,例如 lt、lte、is 等。Query 和 Criteria 类遵循流畅的 API 风格,因此你可以将多个方法标准和查询链式连接在一起,同时保持代码易于理解。为了提高可读性,静态导入可以让你避免使用 new 关键字来创建 Query 和 Criteria 实例。你也可以使用 BasicQuery 从纯 JSON 字符串创建 Query 实例,如以下示例所示:
📄️ 统计文档数量
模板 API 提供了多种方法来统计符合给定条件的文档数量。以下是其中一种方法的概述。
📄️ 聚合框架支持
Spring Data MongoDB 提供了对 MongoDB 2.2 版本引入的聚合框架的支持。