Docs Menu
Docs Home
/ /

Tutorial: Integración con Spring Boot

Spring Boot es un framework Java de código abierto que simplifica el desarrollo de aplicaciones listas para producción. Al combinarse con Spring Data MongoDB, este framework proporciona una forma eficiente de interactuar con bases de datos MongoDB.

Este tutorial muestra cómo crear una aplicación reactiva de Spring Boot que utiliza Spring Data MongoDB para realizar operaciones en una base de datos MongoDB. Puede usar esta aplicación de saldo de caja de ejemplo para llamar a las API REST que realizan las siguientes acciones:

  • Crear o obtener una cuenta

  • Realizar transacciones en una cuenta o entre dos cuentas

Spring Data MongoDB proporciona soporte de repositorio para MongoDB, ofreciendo dos formas principales de interactuar con la base de datos:

  • ReactiveMongoRepository: una abstracción de nivel superior que proporciona acceso a operaciones de base de datos comunes

  • ReactiveMongoTemplate: una abstracción de nivel inferior que ofrece más control sobre las operaciones de MongoDB y la construcción de consultas

MongoDB admite transacciones ACID multidocumento, lo que permite realizar múltiples operaciones que cumplen con las garantías de atomicidad, consistencia, aislamiento y durabilidad. Spring Data MongoDB ofrece compatibilidad integrada con transacciones a través de @Transactional Anotación o la clase TransactionalOperator. La aplicación de ejemplo de este tutorial configura el soporte de transacciones para garantizar la atomicidad de las operaciones de la base de datos.

Para obtener más información sobre las transacciones de MongoDB, consulte Transacciones en el manual del servidor MongoDB.

Este tutorial muestra cómo descargar una aplicación de ejemplo que implementa un sistema simplificado de saldo de caja. La aplicación permite crear, recuperar y actualizar el saldo de cuentas bancarias. Para ver la aplicación completa, consulte el repositorio de GitHub mdb-spring-boot-reactive.

Complete el tutorial para aprender a realizar las siguientes acciones:

  • Descargue una aplicación Spring Boot de ejemplo

  • Configurar la aplicación para conectarse a MongoDB

  • Comprender la estructura de la aplicación y los componentes clave

  • Ejecutar la aplicación

  • Enviar solicitudes POST para crear cuentas bancarias y realizar transacciones

1

Antes de comenzar este tutorial, asegúrese de tener los siguientes componentes preparados:

  • Cuenta de MongoDB Atlas con un clúster configurado. Para aprender a crear un clúster, consulte la guía de introducción a MongoDB.

  • rizo.

  • Java 21 o posterior.

  • Maven. 3 5 o posterior.

2

Clone la aplicación de ejemplo del repositorio GitHub de MongoDB Developer ejecutando el siguiente comando:

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

Este repositorio contiene una aplicación Spring Boot reactiva que utiliza Spring Data MongoDB para interactuar con una base de datos MongoDB.

3

Navegue al archivo src/main/resources/application.properties en el directorio de la aplicación de ejemplo. En este archivo, configure la propiedad spring.data.mongodb.uri con la URI de conexión de Atlas, como se muestra en el siguiente código:

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

Reemplace el marcador de posición <connection URI> con su URI de conexión Atlas.

4

Desde el directorio raíz, ejecute el siguiente comando para configurar la validación del esquema para su aplicación:

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

Este comando crea una restricción que garantiza que el saldo de la cuenta bancaria nunca sea inferior a 0. Reemplace el marcador <connection URI> con la URI de su conexión de Atlas.

1

El archivo AccountController.java contiene los puntos finales de la API REST para crear y obtener cuentas. El archivo define un punto final del método POST que inserta un documento en la colección txn-demo.accounts y un punto final del método GET que encuentra un documento según su valor accountNum. El siguiente código muestra estos 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 punto final devuelve un tipo Mono<Account> de AccountRepository, una interfaz ReactiveMongoRepository que actúa como una abstracción del controlador Java Reactive Streams subyacente.

2

La clase AccountController también incluye los siguientes puntos finales de transacción:

  • Un punto final .../debit que se suma al saldo de una cuenta

  • Un punto final .../credit que resta del saldo de una cuenta

  • Un punto final .../transfer que realiza una transferencia de una cuenta a otra

Estos puntos finales tienen las siguientes definiciones:

@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);
}
//...
}

Un objeto TxnEntry representa un cambio en una sola cuenta, y un objeto Txn puede constar de uno o varios objetos TxnEntry. En el código de ejemplo, los puntos de conexión de débito y crédito crean un nuevo objeto TxnEntry y el punto de conexión de transferencia crea dos objetos TxnEntry.

3

La interfaz AccountRepository extiende ReactiveMongoRepository y define los siguientes métodos de consulta:

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);
}

Los códigos utilizan las siguientes anotaciones que le permiten utilizar marcadores de posición cuando consulta MongoDB, que se sustituyen dinámicamente con argumentos de método:

  • @Query: Anota el método findByAccountNum() y especifica los criterios de consulta para encontrar documentos. El marcador ?0 se sustituye por el valor del parámetro accountNum.

  • @Update: Anota el método findAndIncrementBalanceByAccountNum() y especifica la operación de actualización que se realizará en los documentos coincidentes. El marcador ?1 se sustituye por el valor del parámetro increment para aumentar el saldo mediante el operador $inc de MongoDB.

Nota

Aunque el punto final POST descrito en un paso anterior utiliza el accountRepository.save() método, no es necesario definirlo. El save() método y muchos otros métodos base ya están declarados por interfaces en la cadena de herencia ReactiveMongoRepository de.

4

La clase TxnService gestiona la ejecución de transacciones. Esta clase incluye el siguiente 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(/*...*/);
}
}

La clase TxnService incluye los siguientes métodos:

  • saveTransaction(): Guarda un documento Txn en la colección transactions

  • executeTxn(): Llama al método updateBalances() y luego actualiza el estado de la transacción en el documento Txn

  • updateBalances(): Itera a través de cada TxnEntry y realiza las actualizaciones correspondientes en cada documento account

5

Los métodos saveTransaction() y executeTxn() descritos en el paso anterior utilizan métodos definidos en la clase TxnTemplate. Estos métodos tienen las siguientes definiciones:

@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);
}
//...
}

Estos métodos interactúan con MongoDB mediante ReactiveMongoTemplate.

6

Al transferir dinero entre cuentas, puede usar una transacción multidocumento. Las actualizaciones entre dos cuentas deben ser atómicas, y las transacciones garantizan la atomicidad de los datos.

Para acceder al soporte de transacciones de Spring, la aplicación de muestra agrega el bean ReactiveMongoTransactionManager al archivo ReactiveMongoConfig.java:

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

Puede definir el alcance de una transacción mediante un objeto TransactionalOperator o la anotación @Transactional. La clase TxnService muestra ambos enfoques.

Tip

Transacciones de datos de Spring

Para obtener más información sobre transacciones y sesiones en Spring Data MongoDB, consulte Sesiones y transacciones en la documentación de Spring Data.

1

Para iniciar la aplicación, ejecute los siguientes comandos desde el directorio raíz del proyecto:

mvn spring-boot:run

Tras iniciar la aplicación, puede acceder a ella en http://localhost:8080. A continuación, puede usar los puntos de conexión de la API REST para crear cuentas y realizar transacciones.

2

Para crear una nueva cuenta bancaria que tenga un número de cuenta de 12345, ejecute el siguiente comando en su shell:

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

Este comando envía una solicitud POST al punto final /account para crear un nuevo documento de cuenta bancaria en la colección accounts.

3

Para depositar dinero en la cuenta creada en el paso anterior, ejecute el siguiente comando en su shell:

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

Este comando envía una solicitud al punto final .../debit para aumentar el valor amount del documento account correspondiente en 1000.

4

Para transferir dinero de una cuenta a otra, cree una nueva cuenta que tenga un número de cuenta de 67890:

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

Luego, transfiera 500 dólares a esta nueva cuenta ejecutando el siguiente comando:

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

Este comando envía una solicitud al punto final .../transfer para completar la transferencia de saldo.

Para obtener más información sobre Spring Data MongoDB, consulte la documentación de referencia de Spring Data MongoDB.

Para ver la aplicación de ejemplo completa, consulte el repositorio de GitHub mdb-spring-boot-reactive.

Volver

Encriptación en uso

En esta página