Spring认证中国教育管理中心-Spring Data MongoDB教程九

2021-11-25 15:55:52 浏览数 (1)

原标题: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());
  }
}

0 人点赞