Template API

  • 创建、更新、删除和查询 MongoDB 文档,并提供域对象与 MongoDB 文档之间的映射。

  • 访问 MongoDB 驱动器 API,通过 Execute 回调执行高级任务。

  • 支持 MongoDB 聚合框架,用于执行复杂的查询和数据聚合。

  • 提供 Fluent API,支持更具可读性和可控性的 MongoDB交互。

  • 提供异常翻译,将 MongoDB 特定的异常映射到 Spring 的一致的数据访问异常层次结构。

  • 通过 MongoConverter 接口实现 MongoDB 文档与域类的映射。

位于 org.springframework.data.mongodb.core 包中的 MongoTemplate 及其响应式对应类是 Spring 的 MongoDB 支持的中心类,并提供了一组丰富的功能用于与数据库交互。该模板提供了便利的操作,用于创建、更新、删除和查询 MongoDB 文档,并在您的域对象和 MongoDB 文档之间提供了一个映射。

一旦配置,MongoTemplate 就是线程安全的,并且可以在多个实例中重复使用。

Convenience Methods

MongoTemplate 类实现了 MongoOperations 接口。尽可能让 MongoOperation 上的方法以 MongoDB 驱动器 Collection 对象上可用方法命名,使对习惯使用驱动器 API 的现有的 MongoDB 开发人员而言这个 API 显得较为熟悉。例如,您可以找到诸如 findfindAndModifyfindAndReplacefindOneinsertremovesaveupdateupdateMulti 等方法。设计目标是尽可能轻松地实现 MongoDB 基本驱动器和 MongoOperations 之间的转换。两个 API 之间的主要区别在于 MongoOperations 可以传递域对象而不是 Document。此外,MongoOperations 具有用于 QueryCriteriaUpdate 操作的流畅 API,而不是填充 Document 以指定这些操作的参数。

有关更多信息,请参阅文档的 CRUDQuery 部分。

MongoTemplate 实例上引用操作的首选方式是通过其接口 MongoOperations

Execute Callbacks

MongoTemplate 提供了很多便利方法,可帮助您轻松地执行常见任务。但是,如果您需要直接访问 MongoDB 驱动器的 API,您可以使用几个 Execute 回调方法中的一个。execute 回调为您提供 MongoCollectionMongoDatabase 对象的引用。

  • <T> T execute (Class<?> entityClass, CollectionCallback<T> action): 针对指定类实体集合运行给定的 CollectionCallback

  • <T> T execute (String collectionName, CollectionCallback<T> action): 对给定名称的集合运行给定的 CollectionCallback

  • <T> T execute (DbCallback<T> action): 运行 DbCallback,按需翻译任何异常。Spring Data MongoDB 为 MongoDB 2.2 版本中引入的聚合框架提供支持。

  • <T> T execute (String collectionName, DbCallback<T> action): 对给定名称的集合运行 DbCallback,按需翻译任何异常。

  • <T> T executeInSession (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();

Fluent API

当涉及到与 MongoDB 的更底层交互时,作为中心组件的 MongoTemplate 提供了各种方法,涵盖了广泛的需求,从集合创建、索引创建和 CRUD 操作到更高级的功能,如 Map-Reduce 和聚合。您可以找到每个方法的多个重载。它们中的大多数涵盖了 API 中可选或可为空的部分。

FluentMongoOperationsMongoOperations 的常见方法提供了一个更狭窄的接口,并提供了一个可读性更强、更流畅的 API。入口点(insert(…​)find(…​)update(…​) 等)遵循一个基于运行操作的自然命名模式。从入口点开始,API 被设计为仅提供导致终止方法(在以下示例中为 all 方法)的上下文相关方法,该终止方法调用实际的 MongoOperations 对应部分:

Imperative
List<Jedi> all = template.query(SWCharacter.class) 1
  .inCollection("star-wars") 2
  .as(Jedi.class) 3
  .matching(query(where("jedi").is(true))) 4
  .all();
1 用于映射在查询中使用的字段的类型。
2 如果未在域名类型中定义,则使用集合名称。
3 如果不使用原始域名类型,则使用结果类型。
4 The lookup query.
Reactive
Flux<Jedi> all = template.query(SWCharacter.class)
  .inCollection("star-wars")
  .as(Jedi.class)
  .matching(query(where("jedi").is(true)))
  .all();

使用投影允许 MongoTemplate 通过将实际响应限制为投影目标类型所需的字段来优化结果映射。只要 Query 本身不包含任何字段限制,并且目标类型是闭合接口或 DTO 投影,这一特性都适用。

必须不将映射应用于DBRefs

您可以通过终止方法:first()one()all()stream(),在检索一个实体和将多个实体检索为 ListStream 之间进行切换。

使用 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();

Exception Translation

Spring 框架为各种各样的数据库和映射技术提供了异常翻译。传统上,这是针对 JDBC 和 JPA 的。Spring 对 MongoDB 的支持通过提供 org.springframework.dao.support.PersistenceExceptionTranslator 接口的一个实现,将此功能扩展到 MongoDB 数据库。

将它映射到 Spring 的 consistent data access exception hierarchy 背后的动机是你不需要针对 MongoDB 错误代码编写代码即可编写可移植且具有描述性的异常处理代码。所有 Spring 的数据访问异常都继承自根 DataAccessException 类,因此你能够使用一个 try-catch 块来捕获所有数据库相关的异常。请注意,MongoDB 驱动程序抛出的并非所有异常都继承自 MongoException 类。内部异常和消息被保留,因此不会丢失任何信息。

MongoExceptionTranslator 执行的一些映射是 com.mongodb.Network到 DataAccessResourceFailureExceptionMongoException 错误代码 1003、12001、12010、12011 和 12012 到 InvalidDataAccessApiUsageException。查阅实现以了解有关映射的更多详细信息。

Domain Type Mapping

MongoDB 文档和域类之间的映射是通过委托给 MongoConverter 接口的实现来完成的。Spring 提供了 MappingMongoConverter,但是你也可以编写自己的转换器。虽然 MappingMongoConverter 可以使用其他元数据来指定对象到文档的映射,但它也可以通过使用一些用来映射 ID 和集合名称的约定来转换不包含其他元数据的对象。这些约定和使用映射注解将在 Mapping 章中进行说明。