Java - Mapeamento de POJOs
Avalie esse Início rápido
- Atualizar para o Java 21
- Atualize o driver Java para 5.0.0
- Atualize
logback-classic
para 1.2.13
- Atualizar para o Java 17
- Atualize o driver Java para 4.11.1
- Atualize o mongodb-crypt para 1.8.0
- Atualize o driver Java para 4.2.2.
- Exemplo de criptografia no nível do campo do lado do cliente adicionado.
- Atualize o driver Java para 4.1.1.
- O registro do driver Java agora está ativado por meio da popular APISLF4J, então adicionei logback no
pom.xml
e um arquivo de configuraçãologback.xml
.
Java é uma linguagem de programação orientada a objetos e o MongoDB armazena documentos que se parecem muito com objetos. Na verdade, isso não é uma coincidência, porque essa é a ideia central por trás do MongoDB database.
Nesta publicação no blog, conforme prometido na primeira publicação desta série, mostrarei como mapear automaticamente documentos do MongoDB para Plain Old Java Objects (POJOs) usando apenas o driver do MongoDB.
Usarei o mesmo repositório de sempre nesta série. Se você ainda não tiver uma cópia dele, poderá cloná-lo ou apenas atualizá-lo, caso já o tenha:
1 git clone https://github.com/mongodb-developer/java-quick-start
Se você ainda não configurou seu cluster gratuito no MongoDB Atlas, agora é um ótimo momento para fazê-lo. Você tem todas as instruções nesta postagem do blog.
Se você acompanhou esta série, sabe que temos trabalhado com a coleção
grades
no banco de dados sample_training
. Você pode importá-la facilmente carregando o conjunto de dados de amostra no MongoDB Atlas.Esta é a aparência de um documento do MongoDB no formato JSON estendido. Estou usando o JSON estendido porque é mais fácil identificar os tipos de campo e precisaremos deles para construir os POJOs.
1 { 2 "_id": { 3 "$oid": "56d5f7eb604eb380b0d8d8ce" 4 }, 5 "student_id": { 6 "$numberDouble": "0" 7 }, 8 "scores": [{ 9 "type": "exam", 10 "score": { 11 "$numberDouble": "78.40446309504266" 12 } 13 }, { 14 "type": "quiz", 15 "score": { 16 "$numberDouble": "73.36224783231339" 17 } 18 }, { 19 "type": "homework", 20 "score": { 21 "$numberDouble": "46.980982486720535" 22 } 23 }, { 24 "type": "homework", 25 "score": { 26 "$numberDouble": "76.67556138656222" 27 } 28 }], 29 "class_id": { 30 "$numberDouble": "339" 31 } 32 }
A primeira coisa de que precisamos é de uma representação deste documento em Java. Para cada documento ou subdocumento, preciso de uma classe POJO correspondente.
Como você pode ver no documento acima, tenho o próprio documento principal e uma array de subdocumentos no campo
scores
. Assim, precisaremos de 2 POJOs para representar este documento em Java:- Um para a nota,
- Um para as pontuações.
No pacote
com.mongodb.quickstart.models
, criei dois novos POJOs: Grade.java
e Score.java
.1 package com.mongodb.quickstart.models; 2 3 // imports 4 5 public class Grade { 6 7 private ObjectId id; 8 9 private Double studentId; 10 11 private Double classId; 12 private List<Score> scores; 13 14 // getters and setters with builder pattern 15 // toString() 16 // equals() 17 // hashCode() 18 }
Na classe Grade acima, estou usando
@BsonProperty
para evitar violar as convenções de nomenclatura Java para variáveis, getters e setters. Isso me permite indicar ao mapeador que desejo que o campo "student_id"
em JSON seja mapeado para o campo "studentId"
em Java.1 package com.mongodb.quickstart.models; 2 3 import java.util.Objects; 4 5 public class Score { 6 7 private String type; 8 private Double score; 9 10 // getters and setters with builder pattern 11 // toString() 12 // equals() 13 // hashCode() 14 }
Como você pode ver, tomamos o cuidado de combinar os tipos Java com os tipos de valor JSON para seguir o mesmo modelo de dados. Você pode ler mais sobre tipos e documentos na documentação.
Agora que temos tudo o que precisamos, podemos iniciar o código do driver do MongoDB.
Criei uma nova classe
MappingPOJO
no pacote com.mongodb.quickstart
e aqui estão as principais linhas de código:- Preciso de uma instância
ConnectionString
em vez da usualString
que usei até agora nesta série. Ainda estou recuperando meu URI do MongoDB Atlas das propriedades do sistema. Veja minha publicação no blog de início e configuração se precisar de um lembrete.
1 ConnectionString connectionString = new ConnectionString(System.getProperty("mongodb.uri"));
- Preciso configurar o CodecRegistry para incluir um codec para lidar com a tradução de e para BSON para nossos POJOs.
1 CodecRegistry pojoCodecRegistry = fromProviders(PojoCodecProvider.builder().automatic(true).build());
- E preciso adicionar o registro de codec padrão, que contém todos os codecs padrão. Eles podem lidar com todos os tipos principais em Java, como
Boolean
,Double
,String
,BigDecimal
etc.
1 CodecRegistry codecRegistry = fromRegistries(MongoClientSettings.getDefaultCodecRegistry(), 2 pojoCodecRegistry);
- Agora posso juntar todas as minhas configurações usando
MongoClientSettings
.
1 MongoClientSettings clientSettings = MongoClientSettings.builder() 2 .applyConnectionString(connectionString) 3 .codecRegistry(codecRegistry) 4 .build();
- Posso finalmente inicializar minha conexão com o MongoDB.
1 try (MongoClient mongoClient = MongoClients.create(clientSettings)) { 2 MongoDatabase db = mongoClient.getDatabase("sample_training"); 3 MongoCollection<Grade> grades = db.getCollection("grades", Grade.class); 4 [...] 5 }
Como você pode ver nesta última linha do Java, toda a magia está acontecendo aqui. O
MongoCollection<Grade>
que estou recuperando é digitado por Grade
e não por Document
como de costume.Nas publicações no blog anteriores desta série, mostrei como usar operações CRUD manipulando
MongoCollection<Document>
. Vamos revisar todas as operações CRUD usando POJOs agora.- Esta é uma inserção (criação).
1 Grade newGrade = new Grade().setStudent_id(10003d) 2 .setClass_id(10d) 3 .setScores(List.of(new Score().setType("homework").setScore(50d))); 4 grades.insertOne(newGrade);
- Este é uma descoberta (leitura).
1 Grade grade = grades.find(eq("student_id", 10003d)).first(); 2 System.out.println("Grade found:\t" + grade);
- Esta é uma atualização com um
findOneAndReplace
que retorna a versão mais recente do documento.
1 List<Score> newScores = new ArrayList<>(grade.getScores()); 2 newScores.add(new Score().setType("exam").setScore(42d)); 3 grade.setScores(newScores); 4 Document filterByGradeId = new Document("_id", grade.getId()); 5 FindOneAndReplaceOptions returnDocAfterReplace = new FindOneAndReplaceOptions() 6 .returnDocument(ReturnDocument.AFTER); 7 Grade updatedGrade = grades.findOneAndReplace(filterByGradeId, grade, returnDocAfterReplace); 8 System.out.println("Grade replaced:\t" + updatedGrade);
- E, por fim, este é um
deleteOne
.
1 System.out.println(grades.deleteOne(filterByGradeId));
1 package com.mongodb.quickstart; 2 3 import com.mongodb.ConnectionString; 4 import com.mongodb.MongoClientSettings; 5 import com.mongodb.client.MongoClient; 6 import com.mongodb.client.MongoClients; 7 import com.mongodb.client.MongoCollection; 8 import com.mongodb.client.MongoDatabase; 9 import com.mongodb.client.model.FindOneAndReplaceOptions; 10 import com.mongodb.client.model.ReturnDocument; 11 import com.mongodb.quickstart.models.Grade; 12 import com.mongodb.quickstart.models.Score; 13 import org.bson.codecs.configuration.CodecRegistry; 14 import org.bson.codecs.pojo.PojoCodecProvider; 15 import org.bson.conversions.Bson; 16 17 import java.util.ArrayList; 18 import java.util.List; 19 20 import static com.mongodb.client.model.Filters.eq; 21 import static org.bson.codecs.configuration.CodecRegistries.fromProviders; 22 import static org.bson.codecs.configuration.CodecRegistries.fromRegistries; 23 24 public class MappingPOJO { 25 26 public static void main(String[] args) { 27 ConnectionString connectionString = new ConnectionString(System.getProperty("mongodb.uri")); 28 CodecRegistry pojoCodecRegistry = fromProviders(PojoCodecProvider.builder().automatic(true).build()); 29 CodecRegistry codecRegistry = fromRegistries(MongoClientSettings.getDefaultCodecRegistry(), pojoCodecRegistry); 30 MongoClientSettings clientSettings = MongoClientSettings.builder() 31 .applyConnectionString(connectionString) 32 .codecRegistry(codecRegistry) 33 .build(); 34 try (MongoClient mongoClient = MongoClients.create(clientSettings)) { 35 MongoDatabase db = mongoClient.getDatabase("sample_training"); 36 MongoCollection<Grade> grades = db.getCollection("grades", Grade.class); 37 38 // create a new grade. 39 Grade newGrade = new Grade().setStudentId(10003d) 40 .setClassId(10d) 41 .setScores(List.of(new Score().setType("homework").setScore(50d))); 42 grades.insertOne(newGrade); 43 System.out.println("Grade inserted."); 44 45 // find this grade. 46 Grade grade = grades.find(eq("student_id", 10003d)).first(); 47 System.out.println("Grade found:\t" + grade); 48 49 // update this grade: adding an exam grade 50 List<Score> newScores = new ArrayList<>(grade.getScores()); 51 newScores.add(new Score().setType("exam").setScore(42d)); 52 grade.setScores(newScores); 53 Bson filterByGradeId = eq("_id", grade.getId()); 54 FindOneAndReplaceOptions returnDocAfterReplace = new FindOneAndReplaceOptions().returnDocument(ReturnDocument.AFTER); 55 Grade updatedGrade = grades.findOneAndReplace(filterByGradeId, grade, returnDocAfterReplace); 56 System.out.println("Grade replaced:\t" + updatedGrade); 57 58 // delete this grade 59 System.out.println("Grade deleted:\t" + grades.deleteOne(filterByGradeId)); 60 } 61 } 62 }
Para iniciar esse programa, você pode usar essa linha de comando maven em seu projeto raiz (onde está a pasta
src
) ou em seu IDE favorito.1 mvn compile exec:java -Dexec.mainClass="com.mongodb.quickstart.MappingPOJO" -Dmongodb.uri="mongodb+srv://USERNAME:PASSWORD@cluster0-abcde.mongodb.net/test?w=majority"
O mapeamento de POJOs e seus documentos do MongoDB simplifica muito a sua vida quando você está resolvendo problemas do mundo real com Java, mas com certeza você pode ter sucesso sem usar POJOs.
O MongoDB é um banco de dados de esquema dinâmico, o que significa que seus documentos podem ter esquemas diferentes em uma única coleção. Mapear todos os documentos dessa coleção pode ser um desafio. Então, às vezes, usar o método antigo e a classe
Document
será mais fácil.Se você quiser aprender mais e afundar seu conhecimento com mais rapidez, recomendamos conferir o treinamento Caminho do desenvolvedor MongoDB Java disponível gratuitamente na MongoDB University.
Na próxima publicação no blog, mostrarei o framework de agregação em Java.