模板 API
MongoTemplate
及其响应式对应类(位于 org.springframework.data.mongodb.core
包中)是 Spring MongoDB 支持的中心类,并为与数据库交互提供了丰富的功能集。该模板提供便利操作来创建、更新、删除和查询 MongoDB 文档,并在您的领域对象和 MongoDB 文档之间提供映射。
配置后,MongoTemplate 是线程安全的,可以在多个实例中重复使用。
|
便利方法
MongoTemplate
类实现了 MongoOperations
接口。在尽可能的情况下,MongoOperations
上的方法以 MongoDB 驱动程序 Collection
对象上的可用方法命名,以便让习惯于驱动程序 API 的现有 MongoDB 开发人员熟悉该 API。例如,您可以找到诸如 find
、findAndModify
、findAndReplace
、findOne
、insert
、remove
、save
、update
和 updateMulti
之类的方法。设计目标是尽可能轻松地在基本 MongoDB 驱动程序和 MongoOperations
之间进行转换。这两个 API 之间的一个主要区别是,可以将域对象而不是 Document
传递给 MongoOperations
。此外,MongoOperations
具有用于 Query
、Criteria
和 Update
操作的流畅 API,而不是填充 Document
来指定这些操作的参数。
引用 MongoTemplate 实例上的操作的首选方式是通过其接口 MongoOperations 。
|
执行回调
MongoTemplate
提供了许多便捷方法来帮助您轻松执行常见任务。但是,如果您需要直接访问 MongoDB 驱动程序 API,可以使用多个 Execute
回调方法之一。execute
回调为您提供对 MongoCollection
或 MongoDatabase
对象的引用。
-
<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 的可选或可空部分。
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();
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。 |
您可以通过终止方法在检索单个实体和以 List
或 Stream
检索多个实体之间进行切换: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 DataAccessResourceFailureException
和 MongoException
错误代码 1003、12001、12010、12011 和 12012 到 InvalidDataAccessApiUsageException
。查看实现以获取有关映射的更多详细信息。
域类型映射
MongoDB 文档和域类之间的映射通过委派给 MongoConverter
接口的实现来完成。Spring 提供了 MappingMongoConverter
,但您也可以编写自己的转换器。虽然 MappingMongoConverter
可以使用其他元数据来指定对象到文档的映射,但它也可以使用一些用于映射 ID 和集合名称的约定来转换不包含任何其他元数据的对象。这些约定以及映射注释的使用在 映射 章节中进行了说明。