sql >> Databasteknik >  >> NoSQL >> MongoDB

Spring Data Reactive Repositories med MongoDB

1. Inledning

I den här handledningen ska vi se hur man konfigurerar och implementerar databasoperationer med hjälp av reaktiv programmering genom Spring Data Reactive Repositories med MongoDB.

Vi går igenom de grundläggande användningarna av ReactiveCrud Förråd, ReactiveMongoRepository , samt ReactiveMongoTemplate.

Även om dessa implementeringar använder reaktiv programmering, är det inte det primära fokus i denna handledning.

2. Miljö

För att kunna använda Reactive MongoDB måste vi lägga till beroendet till vår pom.xml.

Vi kommer också att lägga till en inbäddad MongoDB för testning:

<dependencies>
    // ...
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-mongodb-reactive</artifactId>
    </dependency>
    <dependency>
        <groupId>de.flapdoodle.embed</groupId>
        <artifactId>de.flapdoodle.embed.mongo</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

3. Konfiguration

För att aktivera det reaktiva stödet måste vi använda @EnableReactiveMongoRepositories tillsammans med vissa infrastrukturinställningar:

@EnableReactiveMongoRepositories
public class MongoReactiveApplication
  extends AbstractReactiveMongoConfiguration {

    @Bean
    public MongoClient mongoClient() {
        return MongoClients.create();
    }

    @Override
    protected String getDatabaseName() {
        return "reactive";
    }
}

Observera att ovanstående skulle vara nödvändigt om vi använde den fristående MongoDB-installationen. Men eftersom vi använder Spring Boot med inbäddad MongoDB i vårt exempel är ovanstående konfiguration inte nödvändig.

4. Skapa ett dokument

För exemplen nedan, låt oss skapa ett konto klass och kommentera den med @Document för att använda den i databasoperationerna:

@Document
public class Account {
 
    @Id
    private String id;
    private String owner;
    private Double value;
 
    // getters and setters
}

5. Använda Reactive Repositories

Vi är redan bekanta med programmeringsmodellen för repositories, med CRUD-metoderna redan definierade plus stöd för några andra vanliga saker också.

Nu med den reaktiva modellen får vi samma uppsättning metoder och specifikationer, förutom att vi kommer att hantera resultaten och parametrarna på ett reaktivt sätt.

5.1. ReactiveCrudRepository

Vi kan använda detta arkiv på samma sätt som det blockerande CrudRepository :

@Repository
public interface AccountCrudRepository 
  extends ReactiveCrudRepository<Account, String> {
 
    Flux<Account> findAllByValue(String value);
    Mono<Account> findFirstByOwner(Mono<String> owner);
}

Vi kan skicka olika typer av argument som vanligt (String ), inslagna (Valfritt , Ström ), eller reaktiv (Mono , Flöde ) som vi kan se i findFirstByOwner() metod.

5.2. ReactiveMongoRepository

Det finns också ReactiveMongoRepository gränssnitt, som ärver från ReactiveCrudRepository och lägger till några nya frågemetoder:

@Repository
public interface AccountReactiveRepository 
  extends ReactiveMongoRepository<Account, String> { }

Använda ReactiveMongoRepository , kan vi fråga med exempel:

Flux<Account> accountFlux = repository
  .findAll(Example.of(new Account(null, "owner", null)));

Som ett resultat kommer vi att få alla konton det är samma som exemplet.

Med våra arkiv skapade har de redan definierade metoder för att utföra vissa databasoperationer som vi inte behöver implementera:

Mono<Account> accountMono 
  = repository.save(new Account(null, "owner", 12.3));
Mono<Account> accountMono2 = repository
  .findById("123456");

5.3. RxJava2CrudRepository

Med RxJava2CrudRepository, vi har samma beteende som ReactiveCrudRepository, men med resultaten och parametertyperna från RxJava :

@Repository
public interface AccountRxJavaRepository 
  extends RxJava2CrudRepository<Account, String> {
 
    Observable<Account> findAllByValue(Double value);
    Single<Account> findFirstByOwner(Single<String> owner);
}

5.4. Testa våra grundläggande funktioner

För att testa våra förvarsmetoder använder vi testprenumeranten:

@Test
public void givenValue_whenFindAllByValue_thenFindAccount() {
    repository.save(new Account(null, "Bill", 12.3)).block();
    Flux<Account> accountFlux = repository.findAllByValue(12.3);

    StepVerifier
      .create(accountFlux)
      .assertNext(account -> {
          assertEquals("Bill", account.getOwner());
          assertEquals(Double.valueOf(12.3) , account.getValue());
          assertNotNull(account.getId());
      })
      .expectComplete()
      .verify();
}

@Test
public void givenOwner_whenFindFirstByOwner_thenFindAccount() {
    repository.save(new Account(null, "Bill", 12.3)).block();
    Mono<Account> accountMono = repository
      .findFirstByOwner(Mono.just("Bill"));

    StepVerifier
      .create(accountMono)
      .assertNext(account -> {
          assertEquals("Bill", account.getOwner());
          assertEquals(Double.valueOf(12.3) , account.getValue());
          assertNotNull(account.getId());
      })
      .expectComplete()
      .verify();
}

@Test
public void givenAccount_whenSave_thenSaveAccount() {
    Mono<Account> accountMono = repository.save(new Account(null, "Bill", 12.3));

    StepVerifier
      .create(accountMono)
      .assertNext(account -> assertNotNull(account.getId()))
      .expectComplete()
      .verify();
}

6. ReactiveMongoTemplate

Förutom repositories-metoden har viReactiveMongoTemplate .

Först och främst måste vi registrera ReactiveMongoTemplate som en böna:

@Configuration
public class ReactiveMongoConfig {
 
    @Autowired
    MongoClient mongoClient;

    @Bean
    public ReactiveMongoTemplate reactiveMongoTemplate() {
        return new ReactiveMongoTemplate(mongoClient, "test");
    }
}

Och sedan kan vi injicera denna böna i vår tjänst för att utföra databasoperationerna:

@Service
public class AccountTemplateOperations {
 
    @Autowired
    ReactiveMongoTemplate template;

    public Mono<Account> findById(String id) {
        return template.findById(id, Account.class);
    }
 
    public Flux<Account> findAll() {
        return template.findAll(Account.class);
    } 
    public Mono<Account> save(Mono<Account> account) {
        return template.save(account);
    }
}

ReactiveMongoTemplate har även ett antal metoder som inte relaterar till den domän vi har, du kan kolla upp dem i dokumentationen.


  1. Redis Keyspace Notifications med flushdb

  2. Finns det en golvfunktion i Mongodbs aggregeringsramverk?

  3. Mongoid Group By eller MongoDb group by in rails

  4. Mongoose JS findOne returnerar alltid null