Join us at MongoDB.local London on 7 May to unlock new possibilities for your data. Use WEB50 to save 50%.
Register now >
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 para repositorios de MongoDB, ofreciendo dos maneras principales de interactuar con la base de datos:

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

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

MongoDB admite transacciones ACID multidocumento, que te permiten realizar múltiples operaciones que cumplen con las garantías de atomicidad, coherencia, aislamiento y durabilidad. Spring Data MongoDB ofrece soporte de funcionalidad incorporada para transacciones a través de la @Transactional anotación o la clase TransactionalOperator. La aplicación de muestra en 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 te permite crear, recuperar y actualizar el saldo de las cuentas bancarias. Para ver la aplicación completa, consulta el mdb-spring-boot-reactive repositorio de GitHub.

Complete el tutorial para aprender a realizar las siguientes acciones:

  • Descargar una aplicación de ejemplo de Spring Boot

  • Configura la aplicación para conectarse a MongoDB

  • Comprende 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 empezar este tutorial, asegúrate de tener preparados los siguientes componentes:

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, ejecuta el siguiente comando para configurar la validación de esquemas para tu aplicación:

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

Este comando crea una restricción que garantiza que el saldo de la cuenta bancaria nunca esté por debajo de 0. Reemplaza el marcador de posición <connection URI> con tu URI de 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 de acceso de transacciones:

  • Un endpoint .../debit que agrega al saldo de una cuenta

  • Un punto final .../credit que descuenta del balance de una cuenta

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

Estos endpoints 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 Txn puede consistir en uno o varios objetos TxnEntry. En el código de ejemplo, los endpoints de débito y crédito crean un nuevo TxnEntry objeto y el endpoint de transferencia crea dos TxnEntry objetos.

3

La interfaz AccountRepository amplía 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);
}

El código utiliza las siguientes anotaciones que te permiten usar marcadores de posición al query MongoDB, los cuales se sustituyen dinámicamente con los argumentos del 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.

  • @UpdateAnota el método findAndIncrementBalanceByAccountNum() y especifica la operación de actualización que se debe ejecutar en los documentos coincidentes. El marcador ?1 se sustituye por el valor del parámetro increment para aumentar el saldo utilizando 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 de cada documento account

5

Los métodos saveTransaction() y executeTxn() descritos en el paso anterior utilizan ambos 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 usando el ReactiveMongoTemplate.

6

Al transferir dinero entre cuentas, puedes usar una transacción multi-documento. 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 ejemplo añade 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 Spring Data

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

1

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

mvn spring-boot:run

Después de iniciar la aplicación, puedes acceder a ella en http://localhost:8080. Luego puede usar los endpoints 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, ejecuta el siguiente comando en tu shell:

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

Este comando envía una publicación solicitud al endpoint /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 endpoint .../debit para aumentar el valor de amount del documento account correspondiente en 1000.

4

Para transferir dinero de una cuenta a otra, crea una cuenta nueva con el número de cuenta 67890:

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

Luego, transfiere 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 endpoint .../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, consulta el mdb-spring-boot-reactive repositorio de GitHub.

Volver

Encriptación en uso

En esta página