1. Visão geral
Este artigo será uma introdução rápida e prática ao Spring Data MongoDB.
Veremos o básico usando o MongoTemplate bem como MongoRepository , com exemplos práticos para ilustrar cada operação.
Leitura adicional:
Suporte geoespacial no MongoDB
Veja como armazenar, indexar e pesquisar dados geoespaciais com o MongoDBLeia mais →Teste de integração Spring Boot com MongoDB incorporado
Aprenda a usar a solução MongoDB incorporada do Flapdoodle junto com o Spring Boot para executar testes de integração do MongoDB sem problemas.Leia mais →2. MongoTemplate eMongoRepository
O MongoTemplate segue o padrão de modelo padrão no Spring e fornece uma API básica pronta para uso para o mecanismo de persistência subjacente.
O repositório segue a abordagem centrada no Spring Data e vem com operações de API mais flexíveis e complexas, com base nos padrões de acesso bem conhecidos em todos os projetos Spring Data.
Para ambos, precisamos começar definindo a dependência — por exemplo, no pom.xml , com Maven:
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>3.0.3.RELEASE</version>
</dependency>
Para verificar se alguma nova versão da biblioteca foi lançada, acompanhe os lançamentos aqui.
3. Configuração para MongoTemplate
3.1. Configuração XML
Vamos começar com a configuração XML simples para o modelo Mongo:
<mongo:mongo-client id="mongoClient" host="localhost" />
<mongo:db-factory id="mongoDbFactory" dbname="test" mongo-client-ref="mongoClient" />
Primeiro precisamos definir o bean de fábrica responsável por criar instâncias do Mongo.
Em seguida, precisamos realmente definir (e configurar) o bean de modelo:
<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
<constructor-arg ref="mongoDbFactory"/>
</bean>
E, finalmente, precisamos definir um pós-processador para traduzir qualquer MongoExceptions lançado em @Repository classes anotadas:
<bean class=
"org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
3.2. Configuração Java
Vamos agora criar uma configuração semelhante usando a configuração Java estendendo a classe base para a configuração do MongoDB AbstractMongoConfiguration :
@Configuration
public class MongoConfig extends AbstractMongoClientConfiguration {
@Override
protected String getDatabaseName() {
return "test";
}
@Override
public MongoClient mongoClient() {
ConnectionString connectionString = new ConnectionString("mongodb://localhost:27017/test");
MongoClientSettings mongoClientSettings = MongoClientSettings.builder()
.applyConnectionString(connectionString)
.build();
return MongoClients.create(mongoClientSettings);
}
@Override
public Collection getMappingBasePackages() {
return Collections.singleton("com.baeldung");
}
}
Observe que não precisamos definir MongoTemplate bean na configuração anterior, pois já está definido em AbstractMongoClientConfiguration .
Também podemos usar nossa configuração do zero sem estender AbstractMongoClientConfiguration :
@Configuration
public class SimpleMongoConfig {
@Bean
public MongoClient mongo() {
ConnectionString connectionString = new ConnectionString("mongodb://localhost:27017/test");
MongoClientSettings mongoClientSettings = MongoClientSettings.builder()
.applyConnectionString(connectionString)
.build();
return MongoClients.create(mongoClientSettings);
}
@Bean
public MongoTemplate mongoTemplate() throws Exception {
return new MongoTemplate(mongo(), "test");
}
}
4. Configuração para MongoRepository
4.1. Configuração XML
Para fazer uso de repositórios personalizados (estendendo o MongoRepository ), precisamos continuar a configuração da seção 3.1. e configure os repositórios:
<mongo:repositories
base-package="com.baeldung.repository" mongo-template-ref="mongoTemplate"/>
4.2. Configuração Java
Da mesma forma, desenvolveremos a configuração que já criamos na seção 3.2. e adicione uma nova anotação à mistura:
@EnableMongoRepositories(basePackages = "com.baeldung.repository")
4.3. Crie o repositório
Após a configuração, precisamos criar um repositório — estendendo o MongoRepository existente interface:
public interface UserRepository extends MongoRepository<User, String> {
//
}
Agora podemos conectar automaticamente este UserRepository e use operações do MongoRepository ou adicionar operações personalizadas.
5. Usando MongoTemplate
5.1. Inserir
Vamos começar com a operação de inserção, bem como um banco de dados vazio:
{
}
Agora, se inserirmos um novo usuário:
User user = new User();
user.setName("Jon");
mongoTemplate.insert(user, "user");
o banco de dados ficará assim:
{
"_id" : ObjectId("55b4fda5830b550a8c2ca25a"),
"_class" : "com.baeldung.model.User",
"name" : "Jon"
}
5.2. Salvar – Inserir
Osalvar A operação tem uma semântica de salvar ou atualizar:se um id estiver presente, ele executa uma atualização e, se não, ele faz uma inserção.
Vejamos a primeira semântica — a inserção.
Aqui está o estado inicial do banco de dados:
{
}
Quando agora salvamos um novo usuário:
User user = new User();
user.setName("Albert");
mongoTemplate.save(user, "user");
a entidade será inserida no banco de dados:
{
"_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
"_class" : "com.baeldung.model.User",
"name" : "Albert"
}
Em seguida, veremos a mesma operação — salvar — com semântica de atualização.
5.3. Salvar – Atualizar
Vamos agora ver salvar com semântica de atualização, operando em uma entidade existente:
{
"_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
"_class" : "com.baeldung.model.User",
"name" : "Jack"
}
Quando salvamos o usuário existente, vamos atualizá-lo:
user = mongoTemplate.findOne(
Query.query(Criteria.where("name").is("Jack")), User.class);
user.setName("Jim");
mongoTemplate.save(user, "user");
O banco de dados ficará assim:
{
"_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
"_class" : "com.baeldung.model.User",
"name" : "Jim"
}
Podemos ver que neste exemplo em particular, salvar usa a semântica de atualizar porque usamos um objeto com determinado _id .
5.4. Atualizar primeiro
atualizar primeiro atualiza o primeiro documento que corresponde à consulta.
Vamos começar com o estado inicial do banco de dados:
[
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Alex"
},
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614c"),
"_class" : "com.baeldung.model.User",
"name" : "Alex"
}
]
Quando agora executamos o updateFirst :
Query query = new Query();
query.addCriteria(Criteria.where("name").is("Alex"));
Update update = new Update();
update.set("name", "James");
mongoTemplate.updateFirst(query, update, User.class);
apenas a primeira entrada será atualizada:
[
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "James"
},
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614c"),
"_class" : "com.baeldung.model.User",
"name" : "Alex"
}
]
5.5. AtualizarMulti
AtualizarMulti atualiza todos os documentos que correspondem à consulta fornecida.
Primeiro, aqui está o estado do banco de dados antes de fazer o updateMulti :
[
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Eugen"
},
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614c"),
"_class" : "com.baeldung.model.User",
"name" : "Eugen"
}
]
Agora vamos executar o updateMulti Operação:
Query query = new Query();
query.addCriteria(Criteria.where("name").is("Eugen"));
Update update = new Update();
update.set("name", "Victor");
mongoTemplate.updateMulti(query, update, User.class);
Ambos os objetos existentes serão atualizados no banco de dados:
[
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Victor"
},
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614c"),
"_class" : "com.baeldung.model.User",
"name" : "Victor"
}
]
5.6. Localizar e modificar
Esta operação funciona como updateMulti , mas retorna o objeto antes de ser modificado.
Primeiro, este é o estado do banco de dados antes de chamar findAndModify :
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Markus"
}
Vejamos o código de operação real:
Query query = new Query();
query.addCriteria(Criteria.where("name").is("Markus"));
Update update = new Update();
update.set("name", "Nick");
User user = mongoTemplate.findAndModify(query, update, User.class);
O objeto de usuário retornado tem os mesmos valores que o estado inicial no banco de dados.
No entanto, este é o novo estado no banco de dados:
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Nick"
}
5.7. Upsert
O sert funciona na semântica encontrar e modificar else create :se o documento for compatível, atualize-o ou crie um novo documento combinando a consulta e o objeto de atualização.
Vamos começar com o estado inicial do banco de dados:
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Markus"
}
Agora vamos executar o upsert :
Query query = new Query();
query.addCriteria(Criteria.where("name").is("Markus"));
Update update = new Update();
update.set("name", "Nick");
mongoTemplate.upsert(query, update, User.class);
Aqui está o estado do banco de dados após a operação:
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Nick"
}
5.8. Remover
Veremos o estado do banco de dados antes de chamar remove :
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Benn"
}
Agora vamos executar remover :
mongoTemplate.remove(user, "user");
O resultado será o esperado:
{
}
6. Usando o MongoRepository
6.1. Inserir
Primeiro, veremos o estado do banco de dados antes de executar o inserir :
{
}
Agora vamos inserir um novo usuário:
User user = new User();
user.setName("Jon");
userRepository.insert(user);
E aqui está o estado final do banco de dados:
{
"_id" : ObjectId("55b4fda5830b550a8c2ca25a"),
"_class" : "com.baeldung.model.User",
"name" : "Jon"
}
Observe como a operação funciona da mesma forma que inserir no MongoTemplate API.
6.2. Salvar – Inserir
Da mesma forma, salvar funciona da mesma forma que salvar operação no MongoTemplate API.
Vamos começar analisando a semântica de inserção da operação.
Aqui está o estado inicial do banco de dados:
{
}
Agora executamos o salvar Operação:
User user = new User();
user.setName("Aaron");
userRepository.save(user);
Isso resulta na adição do usuário ao banco de dados:
{
"_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
"_class" : "com.baeldung.model.User",
"name" : "Aaron"
}
Observe novamente como salvar funciona com inserir semântica porque estamos inserindo um novo objeto.
6.3. Salvar –Atualizar
Vejamos agora a mesma operação, mas com atualizar semântica.
Primeiro, aqui está o estado do banco de dados antes de executar o novo salvar :
{
"_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
"_class" : "com.baeldung.model.User",
"name" : "Jack"81*6
}
Agora executamos a operação:
user = mongoTemplate.findOne(
Query.query(Criteria.where("name").is("Jack")), User.class);
user.setName("Jim");
userRepository.save(user);
Finalmente, aqui está o estado do banco de dados:
{
"_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
"_class" : "com.baeldung.model.User",
"name" : "Jim"
}
Observe novamente como salvar funciona com atualização semântica porque estamos usando um objeto existente.
6.4. Excluir
Aqui está o estado do banco de dados antes de chamar delete :
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Benn"
}
Vamos executar excluir :
userRepository.delete(user);
E aqui está o nosso resultado:
{
}
6.5. Encontre um
Em seguida, este é o estado do banco de dados quando findOne é chamado:
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Chris"
}
Vamos agora executar o findOne :
userRepository.findOne(user.getId())
E o resultado retornará os dados existentes:
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Chris"
}
6.6. Existe
O estado do banco de dados antes de chamar existe :
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Harris"
}
Agora vamos executar exists , que obviamente retornará true :
boolean isExists = userRepository.exists(user.getId());
6.7. Localizar tudo Com Classificar
O estado do banco de dados antes de chamar findAll :
[
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Brendan"
},
{
"_id" : ObjectId("67b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Adam"
}
]
Vamos agora executar findAll com Classificar :
List<User> users = userRepository.findAll(Sort.by(Sort.Direction.ASC, "name"));
O resultado será classificado por nome em ordem crescente :
[
{
"_id" : ObjectId("67b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Adam"
},
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Brendan"
}
]
6.8. Localizar tudo Com Paginável
O estado do banco de dados antes de chamar findAll :
[
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Brendan"
},
{
"_id" : ObjectId("67b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Adam"
}
]
Vamos agora executar findAll com uma solicitação de paginação:
Pageable pageableRequest = PageRequest.of(0, 1);
Page<User> page = userRepository.findAll(pageableRequest);
List<User> users = pages.getContent();
Os usuários resultantes list será apenas um usuário:
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Brendan"
}
7. Anotações
Por fim, vamos também examinar as anotações simples que o Spring Data usa para conduzir essas operações de API.
O nível de campo @Id anotação pode decorar qualquer tipo, incluindo longa e cadeia :
@Id
private String id;
Se o valor do @Id campo não é nulo, é armazenado no banco de dados como está; caso contrário, o conversor assumirá que queremos armazenar um ObjectId no banco de dados (ou ObjectId , Sequência ou BigInteger trabalhar).
Em seguida, examinaremos @Document :
@Document
public class User {
//
}
Esta anotação simplesmente marca uma classe como sendo um objeto de domínio que precisa ser persistido no banco de dados, além de nos permitir escolher o nome da coleção a ser usada.