模板 API

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

配置后,MongoTemplate 是线程安全的,可以在多个实例中重复使用。

便利方法

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

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

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

执行回调

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 返回有关索引的信息

  • 命令式

  • 响应式

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 的可选或可空部分。

FluentMongoOperationsMongoOperations 的常见方法提供了一个更窄的接口,并提供了一个更具可读性的流畅 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();
1 用于将查询中使用的字段映射到的类型。
2 如果未在域类型上定义,则要使用的集合名称。
3 如果不使用原始域类型,则为结果类型。
4 查找查询。
Flux<Jedi> all = template.query(SWCharacter.class)
  .inCollection("star-wars")
  .as(Jedi.class)
  .matching(query(where("jedi").is(true)))
  .all();
使用投影允许 MongoTemplate 通过将实际响应限制为投影目标类型所需的字段来优化结果映射。只要 Query 本身不包含任何字段限制,并且目标类型是封闭接口或 DTO 投影,此方法就适用。
投影不得应用于 DBRefs

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

使用 near(NearQuery) 编写地理空间查询时,终止方法的数量会更改,仅包括在 MongoDB 中运行 geoNear 命令(在 GeoResults 中以 GeoResult 形式获取实体)有效的那些方法,如下例所示

  • 命令式

  • 响应式

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 to DataAccessResourceFailureExceptionMongoException 错误代码 1003、12001、12010、12011 和 12012 到 InvalidDataAccessApiUsageException。查看实现以获取有关映射的更多详细信息。

域类型映射

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