原标题:Spring认证中国教育管理中心-Spring Data MongoDB教程九(内容来源:Spring中国教育管理中心)
11.21.2.反应性变化流
使用反应式 API 订阅 Change Streams 是处理流的更自然的方法。尽管如此,基本的构建块(例如ChangeStreamOptions)保持不变。以下示例显示了如何使用 Change Streams 发出ChangeStreamEvents:
示例 120. 更改流发射 ChangeStreamEvent
代码语言:javascript复制Flux<ChangeStreamEvent<User>> flux = reactiveTemplate.changeStream(User.class)
.watchCollection("people")
.filter(where("age").gte(38))
.listen();
基础文档应转换为的事件目标类型。保留它以接收未经转换的原始结果。
使用聚合管道或仅查询Criteria来过滤事件。
获取一个Flux变更流事件。的ChangeStreamEvent#getBody()是由式(2)转换为所请求的域的类型。
11.21.3.恢复变更流
可以恢复更改流并在您离开的地方恢复发出事件。要恢复流,您需要提供恢复令牌或上次已知的服务器时间(UTC)。用于相应ChangeStreamOptions地设置值。
以下示例显示如何使用服务器时间设置恢复偏移:
示例 121. 恢复变更流
代码语言:javascript复制Flux<ChangeStreamEvent<User>> resumed = template.changeStream(User.class)
.watchCollection("people")
.resumeAt(Instant.now().minusSeconds(1))
.listen();
您可以ChangeStreamEvent通过getTimestamp方法获取服务器时间,也可以使用resumeToken
公开的方法getResumeToken。
在某些情况下Instant,恢复变更流时可能不够精确。为此目的使用 MongoDB 本机 BsonTimestamp。
11.22.时间序列
MongoDB 5.0 引入了时间序列集合,这些集合经过优化,可以随着时间的推移有效地存储文档,例如测量值或事件。在插入任何数据之前,需要创建这些集合。可以通过运行createCollection命令、定义时间序列集合选项或从@TimeSeries注释中提取选项来创建集合,如下例所示。
示例 122.创建时间序列集合
通过 MongoDB 驱动程序创建时间序列
代码语言:javascript复制template.execute(db -> {
com.mongodb.client.model.CreateCollectionOptions options = new CreateCollectionOptions();
options.timeSeriesOptions(new TimeSeriesOptions("timestamp"));
db.createCollection("天气", 选项);
返回“确定”;
});
创建时间序列集合 CollectionOptions
代码语言:javascript复制template.createCollection("天气", CollectionOptions.timeSeries("timestamp"));
创建从注释派生的时间序列集合
代码语言:javascript复制@TimeSeries(collection="weather", timeField = "timestamp")
公共类测量{
字符串标识;
即时时间戳;
// ...
}
template.createCollection(Measurement.class);
上面的代码片段可以很容易地转移到提供相同方法的反应式 API。确保正确订阅返回的发布者。
12. MongoDB 会话
从 version 3.6 开始,MongoDB 支持 session 的概念。会话的使用启用了 MongoDB 的因果一致性模型,该模型保证以尊重其因果关系的顺序运行操作。这些分为ServerSession实例和ClientSession实例。在本节中,当我们谈到会话时,我们指的是ClientSession。
客户端会话内的操作与会话外的操作并不隔离。
双方MongoOperations并ReactiveMongoOperations提供捆绑的网关的方法ClientSession来操作。MongoCollection并MongoDatabase使用实现 MongoDB 的集合和数据库接口的会话代理对象,因此您无需在每次调用时添加会话。这意味着对 的潜在调用MongoCollection#find()被委托给MongoCollection#find(ClientSession)。
诸如(Reactive)MongoOperations#getCollection返回本机 MongoDB Java Driver 网关对象(例如MongoCollection)之类的方法本身为ClientSession. 这些方法不是会话代理的。ClientSession当直接与 a MongoCollectionor交互时,您应该提供需要的地方,MongoDatabase而不是通过 上的#execute回调之一MongoOperations。
12.1.同步ClientSession支持。
以下示例显示了会话的用法:
例 123.ClientSession与MongoOperations
代码语言:javascript复制ClientSessionOptions sessionOptions = ClientSessionOptions.builder()
.causallyConsistent(true)
.build();
ClientSession session = client.startSession(sessionOptions);
template.withSession(() -> session)
.execute(action -> {
Query query = query(where("name").is("Durzo Blint"));
Person durzo = action.findOne(query, Person.class);
Person azoth = new Person("Kylar Stern");
azoth.setMaster(durzo);
action.insert(azoth);
return azoth;
});
session.close()
从服务器获取新会话。
MongoOperation像以前一样使用方法。在ClientSession被自动应用。
确保关闭ClientSession.
关闭会话。
在处理DBRef实例时,尤其是延迟加载的实例时,在加载所有数据之前不要关闭实例是很重要的ClientSession。否则,延迟获取失败。
12.2.反应式ClientSession支持
反应式对应使用与命令式相同的构建块,如以下示例所示:
例 124.ClientSession 与 ReactiveMongoOperations
代码语言:javascript复制ClientSessionOptions sessionOptions = ClientSessionOptions.builder()
.causallyConsistent(true)
.build();
Publisher<ClientSession> session = client.startSession(sessionOptions);
template.withSession(session)
.execute(action -> {
Query query = query(where("name").is("Durzo Blint"));
return action.findOne(query, Person.class)
.flatMap(durzo -> {
Person azoth = new Person("Kylar Stern");
azoth.setMaster(durzo);
return action.insert(azoth);
});
}, ClientSession::close)
.subscribe();
获取一个Publisher用于新会话检索。
ReactiveMongoOperation像以前一样使用方法。在ClientSession获得并自动应用。
确保关闭ClientSession.
在您订阅之前什么都不会发生。有关详细信息,请参阅Project Reactor 参考指南。
通过使用Publisher提供实际会话的 ,您可以将会话获取推迟到实际订阅点。尽管如此,您需要在完成后关闭会话,以免陈旧的会话污染服务器。当您不再需要会话时,使用doFinally挂机execute进行呼叫ClientSession#close()。如果您更喜欢对会话本身进行更多控制,则可以ClientSession通过驱动程序获取并通过Supplier.
反应式使用ClientSession仅限于模板 API 使用。目前没有与反应式存储库的会话集成。
13. MongoDB 事务
从版本 4 开始,MongoDB 支持Transactions。事务建立在Sessions之上,因此需要一个活动的ClientSession.
除非您MongoTransactionManager在应用程序上下文中指定 a ,否则事务支持是DISABLED。您可以使用setSessionSynchronization(ALWAYS)参与正在进行的非本机 MongoDB 事务。
要获得对事务的完全编程控制,您可能需要在 上使用会话回调MongoOperations。
以下示例显示了 内的编程事务控制SessionCallback:
示例 125. 程序化事务
代码语言:javascript复制ClientSession session = client.startSession(options);
template.withSession(session)
.execute(action -> {
session.startTransaction();
try {
Step step = // ...;
action.insert(step);
process(step);
action.update(Step.class).apply(Update.set("state", // ...
session.commitTransaction();
} catch (RuntimeException e) {
session.abortTransaction();
}
}, ClientSession::close)
获得新的ClientSession.
开始交易。
如果一切都按预期进行,请提交更改。
有些东西坏了,所以回滚一切。
完成后不要忘记关闭会话。
前面的示例使您可以在使用MongoOperations回调中的会话范围实例时完全控制事务行为,以确保将会话传递给每个服务器调用。为了避免这种方法带来的一些开销,您可以使用 aTransactionTemplate来消除手动事务流的一些噪音。
13.1.与TransactionTemplate
Spring Data MongoDB 事务支持TransactionTemplate. 以下示例显示了如何创建和使用TransactionTemplate:
示例 126. 与 TransactionTemplate
代码语言:javascript复制template.setSessionSynchronization(ALWAYS);
// ...
TransactionTemplate txTemplate = new TransactionTemplate(anyTxManager);
txTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
Step step = // ...;
template.insert(step);
process(step);
template.update(Step.class).apply(Update.set("state", // ...
};
});
在模板 API 配置期间启用事务同步。
创建TransactionTemplate使用提供的 PlatformTransactionManager.
在回调中ClientSession,交易已经注册。
MongoTemplate在运行时 更改状态(您可能认为在前面清单的第 1 项中是可能的)会导致线程和可见性问题。
13.2.与MongoTransactionManager
MongoTransactionManager是通向众所周知的 Spring 事务支持的门户。它允许应用程序使用Spring 的托管事务功能。在MongoTransactionManager绑定ClientSession到线程。MongoTemplate检测会话并相应地对与事务相关联的这些资源进行操作。MongoTemplate还可以参与其他正在进行的交易。以下示例显示了如何创建和使用带有 的事务MongoTransactionManager:
示例 127. 与 MongoTransactionManager
代码语言:javascript复制@Configuration
static class Config extends AbstractMongoClientConfiguration {
@Bean
MongoTransactionManager transactionManager(MongoDatabaseFactory dbFactory) {
return new MongoTransactionManager(dbFactory);
}
// ...
}
@Component
public class StateService {
@Transactional
void someBusinessFunction(Step step) {
template.insert(step);
process(step);
template.update(Step.class).apply(Update.set("state", // ...
};
});
MongoTransactionManager在应用程序上下文中注册。
将方法标记为事务性的。
@Transactional(readOnly = true)建议MongoTransactionManager还启动一个事务,将 附加 ClientSession到传出请求。
13.3.反应式事务
与反应式ClientSession支持一样,它ReactiveMongoTemplate提供了在事务内操作的专用方法,而不必担心根据操作结果提交或停止操作。
除非您 ReactiveMongoTransactionManager在应用程序上下文中指定 a ,否则事务支持是DISABLED。您可以使用setSessionSynchronization(ALWAYS)参与正在进行的非本机 MongoDB 事务。
delete在事务流中使用普通的 MongoDB 反应式驱动程序 API a可能如下所示。
示例 128.本机驱动程序支持
代码语言:javascript复制Mono<DeleteResult> result = Mono
.from(client.startSession())
.flatMap(session -> {
session.startTransaction();
return Mono.from(collection.deleteMany(session, ...))
.onErrorResume(e -> Mono.from(session.abortTransaction()).then(Mono.error(e)))
.flatMap(val -> Mono.from(session.commitTransaction()).then(Mono.just(val)))
.doFinally(signal -> session.close());
});
首先,我们显然需要启动会话。
一旦我们ClientSession手头有了,就开始交易。
通过将 传递给操作在事务内ClientSession操作。
如果操作异常完成,我们需要停止事务并保留错误。
或者当然,在成功的情况下提交更改。仍然保留操作结果。
最后,我们需要确保关闭会话。
上述操作的罪魁祸首是保持主要流程DeleteResult而不是通过commitTransaction()或发布的交易结果abortTransaction(),这导致设置相当复杂。
13.4.与TransactionalOperator
Spring Data MongoDB 事务支持TransactionalOperator. 以下示例显示了如何创建和使用TransactionalOperator:
示例 129. 与 TransactionalOperator
代码语言:javascript复制template.setSessionSynchronization(ALWAYS);
// ...
TransactionalOperator rxtx = TransactionalOperator.create(anyTxManager,
new DefaultTransactionDefinition());
Step step = // ...;
template.insert(step);
Mono<Void> process(step)
.then(template.update(Step.class).apply(Update.set("state", …))
.as(rxtx::transactional)
.then();
为事务参与启用事务同步。
创建TransactionalOperator使用提供的 ReactiveTransactionManager.
TransactionalOperator.transactional(…) 为所有上游操作提供事务管理。
13.5.与ReactiveMongoTransactionManager
ReactiveMongoTransactionManager是通向众所周知的 Spring 事务支持的门户。它允许应用程序利用Spring 的托管事务特性。所述ReactiveMongoTransactionManager绑定ClientSession到订户Context。 ReactiveMongoTemplate检测会话并相应地对与事务相关联的这些资源进行操作。 ReactiveMongoTemplate还可以参与其他正在进行的交易。以下示例显示了如何创建和使用带有 的事务ReactiveMongoTransactionManager:
示例 130. 与 ReactiveMongoTransactionManager
代码语言:javascript复制@Configuration
static class Config extends AbstractMongoClientConfiguration {
@Bean
ReactiveMongoTransactionManager transactionManager(ReactiveDatabaseFactory factory) {
return new ReactiveMongoTransactionManager(factory);
}
// ...
}
@Service
public class StateService {
@Transactional
Mono<UpdateResult> someBusinessFunction(Step step) {
return template.insert(step)
.then(process(step))
.then(template.update(Step.class).apply(Update.set("state", …));
};
});
ReactiveMongoTransactionManager在应用程序上下文中注册。
将方法标记为事务性的。
@Transactional(readOnly = true)建议 ReactiveMongoTransactionManager还启动一个事务,将 附加ClientSession到传出请求。
13.6.交易内部的特殊行为
在事务内部,MongoDB 服务器的行为略有不同。
连接设置
MongoDB 驱动程序提供了一个专用的副本集名称配置选项,将驱动程序转换为自动检测模式。此选项有助于在事务期间识别主要副本集节点和命令路由。
确保添加replicaSet到 MongoDB URI。有关详细信息,请参阅连接字符串选项。
集合操作
MongoDB的确实不支持收集操作,如收集创作,在一个事务中。这也会影响首次使用时发生的动态集合创建。因此,请确保已准备好所有必需的结构。
瞬态错误
MongoDB 可以为事务操作期间引发的错误添加特殊标签。这些可能表示可能通过仅重试操作而消失的瞬时故障。我们强烈推荐Spring Retry用于这些目的。然而,可以重写MongoTransactionManager#doCommit(MongoTransactionObject)以实现 MongoDB 参考手册中概述的重试提交操作行为。
数数
MongoDBcount根据收集统计信息进行操作,这些统计信息可能无法反映事务中的实际情况。在多文档事务中发出命令时,服务器响应错误 50851count。一旦MongoTemplate检测到活动事务,所有公开的count()方法都将转换并委托给使用$match和$count运算符的聚合框架,保留Query设置,例如collation.
在聚合计数助手中使用地理命令时存在限制。不能使用以下运算符,必须用不同的运算符替换:
- $where → $expr
- $near→$geoWithin与$center
- $nearSphere→$geoWithin与$centerSphere
使用Criteria.near(…)和 的查询Criteria.nearSphere(…)必须重写为Criteria.within(…)各自的Criteria.withinSphere(…). 同样适用于near必须更改为的存储库查询方法中的查询关键字within。另请参阅 MongoDB JIRA 票证DRIVERS-518以获取进一步参考。
以下代码段显示count了会话绑定闭包中的用法:
代码语言:javascript复制session.startTransaction();
template.withSession(session)
.execute(action -> {
action.count(query(where("state").is("active")), Step.class)
...
上面的代码片段在以下命令中具体化:
代码语言:javascript复制db.collection.aggregate(
[
{ $match: { state: "active" } },
{ $count: "totalEntityCount" }
]
)
代替:
代码语言:javascript复制db.collection.find( { state: "active" } ).count()
14. 反应式 MongoDB 支持
反应式 MongoDB 支持包含以下基本功能集:
- Spring 配置支持使用基于 Java 的@Configuration类、MongoClient实例和副本集。
- ReactiveMongoTemplate,这是一个辅助类,通过MongoOperations以反应方式使用来提高生产力。它包括Document实例和 POJO之间的集成对象映射。
- 异常转换为 Spring 的可移植数据访问异常层次结构。
- 功能丰富的对象映射与 Spring 的ConversionService.
- 基于注释的映射元数据可扩展以支持其他元数据格式。
- 持久性和映射生命周期事件。
- 基于Java的Query,Criteria和UpdateDSL的。
- 响应式存储库接口的自动实现,包括对自定义查询方法的支持。
对于大多数任务,您应该使用ReactiveMongoTemplate或存储库支持,两者都使用丰富的映射功能。ReactiveMongoTemplate是寻找访问功能的地方,例如递增计数器或临时 CRUD 操作。ReactiveMongoTemplate还提供回调方法,以便您可以使用低级 API 工件(例如MongoDatabase)直接与 MongoDB 通信。各种 API 工件的命名约定的目标是复制基础 MongoDB Java 驱动程序中的命名约定,以便您可以将现有知识映射到 Spring API。
14.1.入门
Spring MongoDB 支持需要 MongoDB 2.6 或更高版本和 Java SE 8 或更高版本。
首先,您需要设置一个正在运行的 MongoDB 服务器。有关如何启动 MongoDB 实例的说明,请参阅MongoDB 快速入门指南。安装后,启动 MongoDB 通常只需运行以下命令:${MONGO_HOME}/bin/mongod
要在 STS 中创建 Spring 项目,请转到 File → New → Spring Template Project → Simple Spring Utility Project,然后在出现提示时按 Yes。然后输入一个项目和一个包名,比如 org.spring.mongodb.example。
然后将以下内容添加到 pom.xml 依赖项部分。
代码语言:javascript复制<dependencies>
<!-- other dependency elements omitted -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-reactivestreams</artifactId>
<version>4.4.0</version>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-core</artifactId>
<version>2020.0.13</version>
</dependency>
</dependencies>
MongoDB 使用两种不同的驱动程序来进行阻塞和反应式(非阻塞)数据访问。虽然默认提供阻塞操作,但您可以选择加入反应式使用。
要开始使用一个工作示例,请创建一个简单的Person类来持久化,如下所示:
代码语言:javascript复制@Document
public class Person {
private String id;
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getId() {
return id;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
@Override
public String toString() {
return "Person [id=" id ", name=" name ", age=" age "]";
}
}
然后创建一个应用程序运行,如下:
代码语言:javascript复制public class ReactiveMongoApp {
private static final Logger log = LoggerFactory.getLogger(ReactiveMongoApp.class);
public static void main(String[] args) throws Exception {
CountDownLatch latch = new CountDownLatch(1);
ReactiveMongoTemplate mongoOps = new ReactiveMongoTemplate(MongoClients.create(), "database");
mongoOps.insert(new Person("Joe", 34))
.flatMap(p -> mongoOps.findOne(new Query(where("name").is("Joe")), Person.class))
.doOnNext(person -> log.info(person.toString()))
.flatMap(person -> mongoOps.dropCollection("person"))
.doOnComplete(latch::countDown)
.subscribe();
latch.await();
}
}
运行前面的类会产生以下输出:
代码语言:javascript复制2016-09-20 14:56:57,373 DEBUG .index.MongoPersistentEntityIndexCreator: 124 - Analyzing class class example.ReactiveMongoApp$Person for index information.
2016-09-20 14:56:57,452 DEBUG .data.mongodb.core.ReactiveMongoTemplate: 975 - Inserting Document containing fields: [_class, name, age] in collection: person
2016-09-20 14:56:57,541 DEBUG .data.mongodb.core.ReactiveMongoTemplate:1503 - findOne using query: { "name" : "Joe"} fields: null for class: class example.ReactiveMongoApp$Person in collection: person
2016-09-20 14:56:57,545 DEBUG .data.mongodb.core.ReactiveMongoTemplate:1979 - findOne using query: { "name" : "Joe"} in db.collection: database.person
2016-09-20 14:56:57,567 INFO example.ReactiveMongoApp: 43 - Person [id=57e1321977ac501c68d73104, name=Joe, age=34]
2016-09-20 14:56:57,573 DEBUG .data.mongodb.core.ReactiveMongoTemplate: 528 - Dropped collection [person]
即使在这个简单的例子中,也有一些事情需要注意:
- 您可以ReactiveMongoTemplate通过使用标准com.mongodb.reactivestreams.client.MongoClient对象和要使用的数据库名称来实例化 Spring Mongo( )的中央助手类。
- 映射器针对标准 POJO 对象工作,无需任何额外的元数据(尽管您可以选择提供该信息。请参阅此处。)。
- 约定用于处理 ID 字段,将其转换为ObjectId存储在数据库中的时间。
- 映射约定可以使用字段访问。请注意,Person该类只有 getter。
- 如果构造函数参数名称与存储文档的字段名称匹配,则它们用于实例化对象
有一个包含多个示例的GitHub 存储库,您可以下载并试用这些示例,以了解该库的工作原理。
14.2.使用 Spring 和 Reactive Streams 驱动程序连接到 MongoDB
使用 MongoDB 和 Spring 时的首要任务之一是 com.mongodb.reactivestreams.client.MongoClient使用 IoC 容器创建对象。
14.2.1.使用基于 Java 的元数据注册 MongoClient 实例
以下示例显示了如何使用基于 Java 的 bean 元数据来注册 a 的实例 com.mongodb.reactivestreams.client.MongoClient:
示例 131.com.mongodb.reactivestreams.client.MongoClient使用基于 Java 的 bean 元数据注册对象
代码语言:javascript复制@Configuration
public class AppConfig {
/*
* Use the Reactive Streams Mongo Client API to create a com.mongodb.reactivestreams.client.MongoClient instance.
*/
public @Bean MongoClient reactiveMongoClient() {
return MongoClients.create("mongodb://localhost");
}
}
这种方法让您可以使用标准 com.mongodb.reactivestreams.client.MongoClientAPI(您可能已经知道)。
另一种方法是 com.mongodb.reactivestreams.client.MongoClient使用 Spring 的ReactiveMongoClientFactoryBean. 与com.mongodb.reactivestreams.client.MongoClient直接实例化实例相比,该FactoryBean方法具有额外的优势,即还为容器提供了一个ExceptionTranslator实现,该实现将 MongoDB 异常转换为 Spring 的可移植DataAccessException层次结构中的异常,用于使用注释注释的数据访问类@Repository。Spring 的 DAO 支持特性中@Repository描述了这种层次结构和使用。
以下示例显示了支持@Repository注释类的异常转换的基于 Java 的 bean 元数据:
示例 132.com.mongodb.reactivestreams.client.MongoClient使用 Spring 的 MongoClientFactoryBean注册对象并启用 Spring 的异常转换支持
代码语言:javascript复制@Configuration
public class AppConfig {
/*
* Factory bean that creates the com.mongodb.reactivestreams.client.MongoClient instance
*/
public @Bean ReactiveMongoClientFactoryBean mongoClient() {
ReactiveMongoClientFactoryBean clientFactory = new ReactiveMongoClientFactoryBean();
clientFactory.setHost("localhost");
return clientFactory;
}
}
要访问 com.mongodb.reactivestreams.client.MongoClient由ReactiveMongoClientFactoryBean其他@Configuration类或您自己的类创建的对象,请MongoClient从上下文中获取。
14.2.2.ReactiveMongoDatabaseFactory 接口
虽然 com.mongodb.reactivestreams.client.MongoClient是反应式 MongoDB 驱动程序 API 的入口点,但连接到特定的 MongoDB 数据库实例需要其他信息,例如数据库名称。使用该信息,您可以获得一个com.mongodb.reactivestreams.client.MongoDatabase对象并访问特定 MongoDB 数据库实例的所有功能。Spring 提供了org.springframework.data.mongodb.core.ReactiveMongoDatabaseFactory引导连接到数据库的接口。以下清单显示了ReactiveMongoDatabaseFactory界面:
代码语言:javascript复制public interface ReactiveMongoDatabaseFactory {
/**
* Creates a default {@link MongoDatabase} instance.
*
* @return
* @throws DataAccessException
*/
MongoDatabase getMongoDatabase() throws DataAccessException;
/**
* Creates a {@link MongoDatabase} instance to access the database with the given name.
*
* @param dbName must not be {@literal null} or empty.
* @return
* @throws DataAccessException
*/
MongoDatabase getMongoDatabase(String dbName) throws DataAccessException;
/**
* Exposes a shared {@link MongoExceptionTranslator}.
*
* @return will never be {@literal null}.
*/
PersistenceExceptionTranslator getExceptionTranslator();
}
本 org.springframework.data.mongodb.core.SimpleReactiveMongoDatabaseFactory类实现了ReactiveMongoDatabaseFactory接口,并与一个标准的创建com.mongodb.reactivestreams.client.MongoClient实例和数据库名称。
ReactiveMongoTemplate您可以在标准 Java 代码中使用它们,而不是使用 IoC 容器来创建 的实例,如下所示:
代码语言:javascript复制public class MongoApp {
private static final Log log = LogFactory.getLog(MongoApp.class);
public static void main(String[] args) throws Exception {
ReactiveMongoOperations mongoOps = new ReactiveMongoOperations(new SimpleReactiveMongoDatabaseFactory(MongoClient.create(), "database"));
mongoOps.insert(new Person("Joe", 34))
.flatMap(p -> mongoOps.findOne(new Query(where("name").is("Joe")), Person.class))
.doOnNext(person -> log.info(person.toString()))
.flatMap(person -> mongoOps.dropCollection("person"))
.subscribe();
}
}
使用 SimpleReactiveMongoDatabaseFactory是入门部分中显示的列表之间的唯一区别。
14.2.3.使用基于 Java 的元数据注册 ReactiveMongoDatabaseFactory 实例
要向 ReactiveMongoDatabaseFactory容器注册实例,您可以编写与前面代码清单中突出显示的代码非常相似的代码,如下例所示:
代码语言:javascript复制@Configuration
public class MongoConfiguration {
public @Bean ReactiveMongoDatabaseFactory reactiveMongoDatabaseFactory() {
return new SimpleReactiveMongoDatabaseFactory(MongoClients.create(), "database");
}
}
要定义用户名和密码,请创建一个 MongoDB 连接字符串并将其传递给工厂方法,如下面的清单所示。以下清单还显示了如何使用 ReactiveMongoDatabaseFactory向ReactiveMongoTemplate容器注册实例:
代码语言:javascript复制@Configuration
public class MongoConfiguration {
public @Bean ReactiveMongoDatabaseFactory reactiveMongoDatabaseFactory() {
return new SimpleReactiveMongoDatabaseFactory(MongoClients.create("mongodb://joe:secret@localhost"), "database");
}
public @Bean ReactiveMongoTemplate reactiveMongoTemplate() {
return new ReactiveMongoTemplate(reactiveMongoDatabaseFactory());
}
}