Voyage AI joins MongoDB to power more accurate and trustworthy AI applications on Atlas.

Explore o novo chatbot do Developer Center! O MongoDB AI chatbot pode ser acessado na parte superior da sua navegação para responder a todas as suas perguntas sobre o MongoDB .

APIs REST com Java, Spring Boot e MongoDB

Maxime Beugnet4 min read • Published Oct 25, 2023 • Updated Oct 25, 2023
APLICATIVO COMPLETO
Facebook Icontwitter iconlinkedin icon
Classificar este exemplo de código
star-empty
star-empty
star-empty
star-empty
star-empty

Repositório do GitHub

If you want to write REST APIs in Java at the speed of light, I have what you need. I wrote this template to get you started. I have tried to solve as many problems as possible in it.
Portanto, se você quiser escrever APIs REST em Java, clone este projeto e estará pronto para começar num instante.
1git clone https://github.com/mongodb-developer/java-spring-boot-mongodb-starter
Isso é tudo, gente! Tudo o que você precisa está neste repositório. A seguir, explicarei alguns dos recursos e detalhes sobre esse modelo, mas fique à vontade para ignorar o que não for necessário para sua compreensão.

README

All the extra information and commands you need to get this project going are in the README.md file which you can read in GitHub.

Configuração do Spring e MongoDB

The configuration can be found in the MongoDBConfiguration.java class.
1package com.mongodb.starter;
2
3import [...]
4
5import static org.bson.codecs.configuration.CodecRegistries.fromProviders;
6import static org.bson.codecs.configuration.CodecRegistries.fromRegistries;
7
8@Configuration
9public class MongoDBConfiguration {
10
11 @Value("${spring.data.mongodb.uri}")
12 private String connectionString;
13
14 @Bean
15 public MongoClient mongoClient() {
16 CodecRegistry pojoCodecRegistry = fromProviders(PojoCodecProvider.builder().automatic(true).build());
17 CodecRegistry codecRegistry = fromRegistries(MongoClientSettings.getDefaultCodecRegistry(), pojoCodecRegistry);
18 return MongoClients.create(MongoClientSettings.builder()
19 .applyConnectionString(new ConnectionString(connectionString))
20 .codecRegistry(codecRegistry)
21 .build());
22 }
23
24}
The important section here is the MongoDB configuration, of course. Firstly, you will notice the connection string is automatically retrieved from the application.properties file, and secondly, you will notice the configuration of the MongoClient bean.
uma Codec is the interface that abstracts the processes of decoding a BSON value into a Java object and encoding a Java object into a BSON value.
uma CodecRegistry contains a set of Codec instances that are accessed according to the Java classes that they encode from and decode to.
O driver do MongoDB é capaz de codificar e decodificar BSON para nós, portanto, não precisamos mais lidar com isso. Toda a configuração de que precisamos para que este projeto seja executado está aqui e em nenhum outro lugar.
You can read the driver documentation if you want to know more about this topic.

Transações ACID multidocumento

Just for the sake of it, I also used multi-document ACID transactions in a few methods where it could potentially make sense to use ACID transactions. You can check all the code in the MongoDBPersonRepository class.
Aqui está um exemplo:
1private static final TransactionOptions txnOptions = TransactionOptions.builder()
2 .readPreference(ReadPreference.primary())
3 .readConcern(ReadConcern.MAJORITY)
4 .writeConcern(WriteConcern.MAJORITY)
5 .build();
6
7@Override
8public List<PersonEntity> saveAll(List<PersonEntity> personEntities) {
9 try (ClientSession clientSession = client.startSession()) {
10 return clientSession.withTransaction(() -> {
11 personEntities.forEach(p -> p.setId(new ObjectId()));
12 personCollection.insertMany(clientSession, personEntities);
13 return personEntities;
14 }, txnOptions);
15 }
16}
Como você pode ver, estou usando um try-with-resources com fechamento automático, que fechará automaticamente a sessão do cliente no final. Isso me ajuda a manter o código limpo e simples.
Alguns de vocês podem argumentar que isso é simples demais porque as transação (e operações de gravação, em geral) podem lançar exceções, e não estou lidando com nenhuma delas aqui... Vocês estão absolutamente certos e essa é uma excelente transição para a próxima parte deste artigo.

Gerenciamento de exceções

Transactions in MongoDB can raise exceptions for various reasons, and I don’t want to go into the details too much here, but since MongoDB 3.6, any write operation that fails can be automatically retried once. And the transactions are no different. See the documentation for retryWrites.
Se as gravações repetitivas estiverem desabilitadas ou se uma operação de gravação falhar duas vezes, o MongoDB enviará uma MongoException (extende RuntimeException) que deve ser tratada corretamente.
Luckily, Spring provides the annotation ExceptionHandler to help us do that. See the code in my controller PersonController. Of course, you will need to adapt and enhance this in your real project, but you have the main idea here.
1@ExceptionHandler(RuntimeException.class)
2public final ResponseEntity<Exception> handleAllExceptions(RuntimeException e) {
3 logger.error("Internal server error.", e);
4 return new ResponseEntity<>(e, HttpStatus.INTERNAL_SERVER_ERROR);
5}

Pipeline de agregação

MongoDB's aggregation pipeline is a very powerful and efficient way to run your complex queries as close as possible to your data for maximum efficiency. Using it can ease the computational load on your application.
Just to give you a small example, I implemented the /api/persons/averageAge route to show you how I can retrieve the average age of the persons in my collection.
1@Override
2public double getAverageAge() {
3 List<Bson> pipeline = List.of(group(new BsonNull(), avg("averageAge", "$age")), project(excludeId()));
4 return personCollection.aggregate(pipeline, AverageAgeDTO.class).first().averageAge();
5}
Also, you can note here that I’m using the personCollection which was initially instantiated like this:
1private MongoCollection<PersonEntity> personCollection;
2
3@PostConstruct
4void init() {
5 personCollection = client.getDatabase("test").getCollection("persons", PersonEntity.class);
6}
Normally, my personCollection should encode and decode PersonEntity object only, but you can overwrite the type of object your collection is manipulating to return something different — in my case, AverageAgeDTO.class as I’m not expecting a PersonEntity class here but a POJO that contains only the average age of my "persons".

Swagger

Swagger is the tool you need to document your REST APIs. You have nothing to do — the configuration is completely automated. Just run the server and navigate to http://localhost:8080/swagger-ui.html. the interface will be waiting for you.
The Swagger UI
Você pode testar as APIs REST a partir desta página da web e explorar os modelos. Não se esqueça de desativá-lo na produção. ;-)
Isso é tudo que fiz para que funcionasse:
1<dependency>
2 <groupId>org.springdoc</groupId>
3 <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
4 <version>2.2.0</version>
5</dependency>
See the documentation for more information.

Nyan Cat

Sim, há uma seção Nyan Cat nesta publicação. Nyan Cat é amor, e você precisa de um pouco de Nyan Cat em seus projetos. :-)
Você sabia que pode substituir o logotipo do Spring Boot nos registros por praticamente qualquer coisa que quiser?
Nyan Cat
Bem, agora você sabe. Você é bem-vindo.
Have a look at the banner.txt file if you want to replace this awesome Nyan Cat with your own custom logo.
I like to use patorjk and the "Epic" font for each project name. It's easier to identify which log file I am currently reading.

Conclusão

Espero que você goste do meu modelo. Posso ajudá-lo a ser mais produtivo com o MongoDB e a pilha Java.
If you see something which can be improved, please feel free to open a GitHub issue or directly submit a pull request. They are very welcome. :-)
If you are new to MongoDB Atlas, give our Quick Start post a try to get up to speed with MongoDB Atlas in no time.

Facebook Icontwitter iconlinkedin icon
Classificar este exemplo de código
star-empty
star-empty
star-empty
star-empty
star-empty
Relacionado
Artigo

Como otimizar o desempenho do Java com threads virtuais, programação reativa e MongoDB


Aug 29, 2024 | 5 min read
Artigo

Driver Java: migrando do 4.11 a 5.0


Mar 01, 2024 | 3 min read
Artigo

Orquestração do MongoDB com o Spring e Atlas Kubernetes Operator


Jun 12, 2024 | 13 min read
Artigo

Por que dados não estruturados são uma boa opção para Java


Sep 16, 2024 | 7 min read