Join us at MongoDB.local London on 7 May to unlock new possibilities for your data. Use WEB50 to save 50%.
Register now >
Menu Docs
Página inicial do Docs
/ /

Tutorial: Integração com o Spring Boot

Spring Boot é um framework Java de código aberto que simplifica o desenvolvimento de aplicativos prontos para produção. Quando combinada com Spring Data MongoDB, esse framework fornece uma maneira eficiente de interagir com bancos de dados MongoDB.

Este tutorial demonstra como criar um aplicativo reativo Spring Boot que utiliza o Spring Data MongoDB para executar operações em um banco de dados MongoDB. Você pode usar essa amostra de aplicativo de saldo de caixa para chamar APIs REST que executam as seguintes ações:

  • Criar ou buscar uma conta

  • Realizar transações em uma conta ou entre duas contas

Spring Data MongoDB fornece suporte de repositório para MongoDB, oferecendo duas maneiras principais de interagir com o banco de dados:

  • ReactiveMongoRepository: Uma abstração de nível superior que fornece acesso a operações comuns do banco de dados

  • ReactiveMongoTemplate: Uma abstração de nível inferior que oferece mais controle sobre as operações do MongoDB e a construção de queries

O MongoDB oferece suporte a transações ACID de vários documentos, que permitem executar várias operações que atendem garantias de atomicidade, consistência, isolamento e durabilidade. O Spring Data MongoDB oferece suporte integrado para transações por meio da anotação @Transactional ou da classe TransactionalOperator. O aplicativo de amostra neste tutorial configura o suporte a transações para garantir a atomicidade das operações do banco de dados.

Para aprender mais sobre transações MongoDB, consulte Transações no manual do MongoDB Server.

Este tutorial mostra como baixar um exemplo de aplicativo que implementa um sistema simplificado de saldo de caixa. O aplicativo permite criar, recuperar e atualizar o saldo de contas bancárias. Para visualizar o aplicativo completo, consulte o repositório GitHub mdb-spring-boot-reactive.

Conclua o tutorial para aprender como executar as seguintes ações:

  • Baixe um exemplo de aplicativo Spring Boot

  • Configure o aplicativo para se conectar ao MongoDB

  • Compreender a estrutura do aplicativo e os principais componentes

  • Execute o aplicativo

  • Enviar solicitações POST para criar contas bancárias e realizar transações

1

Antes de iniciar este tutorial, verifique se você tem os seguintes componentes preparados:

2

Clone o aplicativo de exemplo do repositório do MongoDB desenvolvedor GitHub executando o seguinte comando:

git clone git@github.com:mongodb-developer/mdb-spring-boot-reactive.git

Este repositório contém um aplicativo reativo Spring Boot que usa o Spring Data MongoDB para interagir com um banco de dados MongoDB.

3

Navegue até o arquivo src/main/resources/application.properties no diretório do aplicativo de exemplo. Neste arquivo, defina a propriedade spring.data.mongodb.uri para seu URI de conexão do Atlas , conforme mostrado no código a seguir:

spring.data.mongodb.uri=<connection URI>

Substitua o espaço reservado <connection URI> pelo URI de conexão do Atlas .

4

No diretório raiz, execute o seguinte comando para configurar a validação de esquema para seu aplicativo:

mongosh "<connection URI>" --file setup.js

Este comando cria uma restrição que garante que o saldo da conta bancária nunca fique abaixo de 0. Substitua o espaço reservado <connection URI> pelo URI de conexão do Atlas .

1

O arquivo AccountController.java contém pontos de extremidade da REST API para criar e buscar contas. O arquivo define um ponto de extremidade de método POST que insere um documento na coleção txn-demo.accounts e um ponto de extremidade de método GET que encontra um documento com base em seu valor de accountNum. O seguinte código mostra estes métodos:

@RestController
public class AccountController {
//...
@PostMapping("/account")
public Mono<Account> createAccount(@RequestBody Account account) {
return accountRepository.save(account);
}
@GetMapping("/account/{accountNum}")
public Mono<Account> getAccount(@PathVariable String accountNum) {
return accountRepository.findByAccountNum(accountNum)
.switchIfEmpty(Mono.error(new AccountNotFoundException()));
}
//...
}

Cada ponto de extremidade retorna um tipo Mono<Account> de AccountRepository, uma interface ReactiveMongoRepository que atua como uma abstração do driver Java Reactive Streams subjacente.

2

A classe AccountController também inclui os seguintes pontos de extremidade de transação:

  • Um .../debit ponto de extremidade que adiciona ao saldo de uma conta

  • Um .../credit ponto de extremidade que subtrai de um saldo de conta

  • Um .../transfer ponto de extremidade que executa uma transferência de uma conta para outra

Esses pontos de extremidade têm as seguintes definições:

@RestController
public class AccountController {
//...
@PostMapping("/account/{accountNum}/debit")
public Mono<Txn> debitAccount(@PathVariable String accountNum,
@RequestBody Map<String, Object> requestBody) {
//...
txn.addEntry(new TxnEntry(accountNum, amount));
return txnService.saveTransaction(txn).flatMap(txnService::executeTxn);
}
@PostMapping("/account/{accountNum}/credit")
public Mono<Txn> creditAccount(@PathVariable String accountNum,
@RequestBody Map<String, Object> requestBody) {
//...
txn.addEntry(new TxnEntry(accountNum, -amount));
return txnService.saveTransaction(txn).flatMap(txnService::executeTxn);
}
@PostMapping("/account/{from}/transfer")
public Mono<Txn> transfer(@PathVariable String from,
@RequestBody TransferRequest transferRequest) {
//...
txn.addEntry(new TxnEntry(from, -amount));
txn.addEntry(new TxnEntry(to, amount));
return txnService.saveTransaction(txn).flatMap(txnService::executeTxn);
}
//...
}

Um objeto TxnEntry representa uma alteração em uma única conta, e um Txn pode consistir em um ou vários objetos TxnEntry. No código de amostra, os pontos de extremidade de débito e crédito criam um novo objeto TxnEntry, e o ponto de extremidade de transferência cria dois objetos TxnEntry.

3

A interface do AccountRepository estende o ReactiveMongoRepository e define os seguintes métodos de query:

public interface AccountRepository extends ReactiveMongoRepository<Account, String> {
@Query("{accountNum:'?0'}")
Mono<Account> findByAccountNum(String accountNum);
@Update("{'$inc':{'balance': ?1}}")
Mono<Long> findAndIncrementBalanceByAccountNum(String accountNum, double increment);
}

Os códigos usam as seguintes anotações que permitem usar espaços reservados ao executar query do MongoDB, que são dinamicamente substituídos por argumentos do método:

  • @Query: Anota o método findByAccountNum() e especifica os critérios de query para localizar documentos. O espaço reservado ?0 é substituído pelo valor de parâmetro accountNum .

  • @Update: anota o método findAndIncrementBalanceByAccountNum() e especifica a operação de atualizar a ser executada nos documentos correspondentes. O espaço reservado ?1 é substituído pelo valor do parâmetro increment para aumentar o equilíbrio usando o operador $inc do MongoDB.

Observação

Embora o ponto de extremidade publicação descrito em uma etapa anterior utilize o método accountRepository.save(), você não precisa definir este método. O método save() e muitos outros métodos básicos já estão declarados por interfaces na cadeia de herança de ReactiveMongoRepository.

4

A classe TxnService lida com a execução da transação. Esta classe inclui o seguinte código:

@Service
public class TxnService {
//...
public Mono<Txn> saveTransaction(Txn txn) {
return txnTemplate.save(txn);
}
public Mono<Txn> executeTxn(Txn txn) {
return updateBalances(txn)
.onErrorResume(DataIntegrityViolationException.class
/*lambda expression to handle error*/)
.onErrorResume(AccountNotFoundException.class
/*lambda expression to handle error*/)
.then(txnTemplate.findAndUpdateStatusById(txn.getId(), TxnStatus.SUCCESS));
}
public Flux<Long> updateBalances(Txn txn) {
Flux<Long> updatedCounts = Flux.fromIterable(txn.getEntries()).concatMap(
entry -> accountRepository.findAndIncrementBalanceByAccountNum(
entry.getAccountNum(), entry.getAmount())
);
return updatedCounts.handle(/*...*/);
}
}

A classe TxnService inclui os seguintes métodos:

  • saveTransaction(): salva um documento Txn na coleção transactions

  • executeTxn(): chama o método updateBalances() e atualiza o status da transação no documento Txn

  • updateBalances(): Itera por cada TxnEntry e faz as atualizações correspondentes a cada documento account

5

Os métodos saveTransaction() e executeTxn() descritos na etapa anterior usam métodos definidos na classe TxnTemplate . Esses métodos têm as seguintes definições:

@Service
public class TxnTemplate {
//...
public Mono<Txn> save(Txn txn) {
return template.save(txn);
}
public Mono<Txn> findAndUpdateStatusById(String id, TxnStatus status) {
Query query = query(where("_id").is(id));
Update update = update("status", status);
FindAndModifyOptions options = FindAndModifyOptions.options().returnNew(true);
return template.findAndModify(query, update, options, Txn.class);
}
//...
}

Estes métodos interagem com MongoDB utilizando o ReactiveMongoTemplate.

6

Ao transferir dinheiro entre contas, você pode usar uma transação multidocumento. As atualizações em duas contas devem ser atômicas, e as transações garantem a atomicidade dos dados.

Para acessar o suporte a transações do Spring, o aplicativo de amostra adiciona o ReactiveMongoTransactionManager bean ao arquivo ReactiveMongoConfig.java:

@Configuration
public class ReactiveMongoConfig extends AbstractReactiveMongoConfiguration {
//...
@Bean
ReactiveMongoTransactionManager transactionManager(ReactiveMongoDatabaseFactory dbFactory) {
return new ReactiveMongoTransactionManager(dbFactory);
}
}

Você pode definir o escopo de uma transação usando um objeto TransactionalOperator ou a anotação @Transactional. A classe TxnService mostra ambas as abordagens.

Dica

Transações de dados da primavera

Para aprender mais sobre transações e sessões no Spring Data MongoDB, consulte Sessões e transações na documentação do Spring Data.

1

Para iniciar o aplicativo, execute os seguintes comandos no diretório raiz do projeto:

mvn spring-boot:run

Após iniciar o aplicativo, você pode acessá-lo em http://localhost:8080. Em seguida, você pode usar os pontos de extremidade da REST API para criar contas e executar transações.

2

Para criar uma nova conta bancária que tenha um número de conta de 12345, execute o seguinte comando na sua shell:

curl --location 'localhost:8080/account' \
--header 'Content-Type: application/json' \
--data '{
"accountNum": "12345"
}'

Este comando envia uma solicitação POST para o ponto de extremidade /account para criar um novo documento de conta bancária na coleção accounts.

3

Para devolver o valor à conta criada na etapa anterior, execute o seguinte comando em seu shell:

curl --location 'localhost:8080/account/12345/debit' \
--header 'Content-Type: application/json' \
--data '{
"amount": 1000
}'

Este comando envia uma solicitação ao ponto de extremidade .../debit para aumentar o valor amount do documento account correspondente em 1000.

4

Para transferir dinheiro de uma conta para outra, crie uma nova conta que tenha um número de conta de 67890:

curl --location 'localhost:8080/account' \
--header 'Content-Type: application/json' \
--data '{
"accountNum": "67890"
}'

Em seguida, transfira 500 dólares para esta nova conta executando o seguinte comando:

curl --location 'localhost:8080/account/12345/transfer' \
--header 'Content-Type: application/json' \
--data '{
"to": "67890",
"amount": 500
}'

Este comando envia uma solicitação para o ponto de extremidade .../transfer para concluir a transferência de saldo.

Para aprender mais sobre o Spring Data MongoDB, consulte a documentação de referência do Spring Data MongoDB.

Para visualizar o aplicativo de exemplo completo, consulte o repositório Github mdb-spring-boot-reactive.

Voltar

Criptografia em execução

Nesta página