1. Panoramica
Questo articolo sarà una rapida e pratica introduzione a Spring Data MongoDB.
Esamineremo le nozioni di base utilizzando sia il MongoTemplate così come MongoRepository , con esempi pratici per illustrare ogni operazione.
Ulteriori letture:
Supporto geospaziale in MongoDB
Dai un'occhiata a come archiviare, indicizzare e cercare dati geospaziali con MongoDBLeggi di più →Test di integrazione Spring Boot con MongoDB integrato
Scopri come utilizzare la soluzione MongoDB incorporata di Flapdoodle insieme a Spring Boot per eseguire senza problemi i test di integrazione di MongoDB.Leggi di più →2. Modello Mongo e MongoRepository
Il Modello Mongo segue il modello di modello standard in primavera e fornisce un'API di base pronta per l'uso al motore di persistenza sottostante.
Il deposito segue l'approccio Spring Data-centric e include operazioni API più flessibili e complesse, basate sui modelli di accesso ben noti in tutti i progetti Spring Data.
Per entrambi, dobbiamo iniziare definendo la dipendenza, ad esempio in pom.xml , con Maven:
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>3.0.3.RELEASE</version>
</dependency>
Per verificare se è stata rilasciata una nuova versione della libreria, monitora le versioni qui.
3. Configurazione per MongoTemplate
3.1. Configurazione XML
Iniziamo con la semplice configurazione XML per il modello Mongo:
<mongo:mongo-client id="mongoClient" host="localhost" />
<mongo:db-factory id="mongoDbFactory" dbname="test" mongo-client-ref="mongoClient" />
Per prima cosa dobbiamo definire il bean factory responsabile della creazione di istanze Mongo.
Successivamente, dobbiamo effettivamente definire (e configurare) il bean modello:
<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
<constructor-arg ref="mongoDbFactory"/>
</bean>
Infine, dobbiamo definire un post processor per tradurre qualsiasi MongoExceptions lanciato in @Repository classi annotate:
<bean class=
"org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
3.2. Configurazione Java
Creiamo ora una configurazione simile usando la configurazione Java estendendo la classe base per la configurazione di 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");
}
}
Tieni presente che non era necessario definire MongoTemplate bean nella configurazione precedente poiché è già definito in AbstractMongoClientConfiguration .
Possiamo anche utilizzare la nostra configurazione da zero senza estendere 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. Configurazione per MongoRepository
4.1. Configurazione XML
Per utilizzare repository personalizzati (estendendo il MongoRepository ), è necessario continuare la configurazione dalla sezione 3.1. e imposta i repository:
<mongo:repositories
base-package="com.baeldung.repository" mongo-template-ref="mongoTemplate"/>
4.2. Configurazione Java
Allo stesso modo, costruiremo sulla configurazione che abbiamo già creato nella sezione 3.2. e aggiungi una nuova annotazione nel mix:
@EnableMongoRepositories(basePackages = "com.baeldung.repository")
4.3. Crea il repository
Dopo la configurazione, dobbiamo creare un repository, estendendo il MongoRepository esistente interfaccia:
public interface UserRepository extends MongoRepository<User, String> {
//
}
Ora possiamo cablare automaticamente questo UserRepository e usa le operazioni da MongoRepository o aggiungi operazioni personalizzate.
5. Utilizzando MongoTemplate
5.1. Inserisci
Iniziamo con l'operazione di inserimento e con un database vuoto:
{
}
Ora se inseriamo un nuovo utente:
User user = new User();
user.setName("Jon");
mongoTemplate.insert(user, "user");
il database sarà simile a questo:
{
"_id" : ObjectId("55b4fda5830b550a8c2ca25a"),
"_class" : "com.baeldung.model.User",
"name" : "Jon"
}
5.2. Salva – Inserisci
Il salva l'operazione ha una semantica di salvataggio o aggiornamento:se è presente un id, esegue un aggiornamento e, in caso contrario, esegue un inserimento.
Diamo un'occhiata alla prima semantica:l'inserto.
Ecco lo stato iniziale del database:
{
}
Quando ora salviamo un nuovo utente:
User user = new User();
user.setName("Albert");
mongoTemplate.save(user, "user");
l'entità verrà inserita nel database:
{
"_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
"_class" : "com.baeldung.model.User",
"name" : "Albert"
}
Successivamente, esamineremo la stessa operazione:salva — con semantica di aggiornamento.
5.3. Salva – Aggiorna
Diamo ora un'occhiata a salva con semantica di aggiornamento, operando su un'entità esistente:
{
"_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
"_class" : "com.baeldung.model.User",
"name" : "Jack"
}
Quando salviamo l'utente esistente, lo aggiorneremo:
user = mongoTemplate.findOne(
Query.query(Criteria.where("name").is("Jack")), User.class);
user.setName("Jim");
mongoTemplate.save(user, "user");
Il database sarà simile a questo:
{
"_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
"_class" : "com.baeldung.model.User",
"name" : "Jim"
}
Possiamo vedere che in questo particolare esempio, salva utilizza la semantica di aggiornamento perché usiamo un oggetto con _id dato .
5.4. UpdateFirst
updateFirst aggiorna il primo documento che corrisponde alla query.
Iniziamo con lo stato iniziale del database:
[
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Alex"
},
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614c"),
"_class" : "com.baeldung.model.User",
"name" : "Alex"
}
]
Quando ora eseguiamo 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);
solo la prima voce verrà aggiornata:
[
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "James"
},
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614c"),
"_class" : "com.baeldung.model.User",
"name" : "Alex"
}
]
5.5. Aggiorna Multi
Aggiorna Multi aggiorna tutti i documenti che corrispondono alla query specificata.
Innanzitutto, ecco lo stato del database prima di eseguire updateMulti :
[
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Eugen"
},
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614c"),
"_class" : "com.baeldung.model.User",
"name" : "Eugen"
}
]
Ora eseguiamo updateMulti operazione:
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);
Entrambi gli oggetti esistenti verranno aggiornati nel database:
[
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Victor"
},
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614c"),
"_class" : "com.baeldung.model.User",
"name" : "Victor"
}
]
5.6. Trova e modifica
Questa operazione funziona come updateMulti , ma restituisce l'oggetto prima che fosse modificato.
Innanzitutto, questo è lo stato del database prima di chiamare findAndModify :
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Markus"
}
Diamo un'occhiata al codice operativo effettivo:
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);
L'oggetto utente restituito ha gli stessi valori dello stato iniziale nel database.
Tuttavia, questo è il nuovo stato nel database:
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Nick"
}
5.7. Inserimento
Il sottosopra funziona su trova e modifica altro crea semantica :se il documento è abbinato, aggiornalo, oppure crea un nuovo documento combinando l'oggetto query e update.
Iniziamo con lo stato iniziale del database:
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Markus"
}
Ora eseguiamo l'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);
Ecco lo stato del database dopo l'operazione:
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Nick"
}
5.8. Rimuovi
Esamineremo lo stato del database prima di chiamare remove :
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Benn"
}
Ora eseguiamo remove :
mongoTemplate.remove(user, "user");
Il risultato sarà come previsto:
{
}
6. Utilizzando MongoRepository
6.1. Inserisci
Per prima cosa, vedremo lo stato del database prima di eseguire l'insert :
{
}
Ora inseriamo un nuovo utente:
User user = new User();
user.setName("Jon");
userRepository.insert(user);
Ed ecco lo stato finale del database:
{
"_id" : ObjectId("55b4fda5830b550a8c2ca25a"),
"_class" : "com.baeldung.model.User",
"name" : "Jon"
}
Nota come l'operazione funziona allo stesso modo dell'inserto nel Modello Mongo API.
6.2. Salva – Inserisci
Allo stesso modo, salva funziona come il salvataggio operazione nelMongoTemplate API.
Iniziamo osservando la semantica di inserimento dell'operazione.
Ecco lo stato iniziale del database:
{
}
Ora eseguiamo il salvataggio operazione:
User user = new User();
user.setName("Aaron");
userRepository.save(user);
Ciò comporta l'aggiunta dell'utente al database:
{
"_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
"_class" : "com.baeldung.model.User",
"name" : "Aaron"
}
Nota ancora come salvare funziona con inserire semantica perché stiamo inserendo un nuovo oggetto.
6.3. Salva – Aggiorna
Esaminiamo ora la stessa operazione ma con aggiornamento semantica.
Innanzitutto, ecco lo stato del database prima di eseguire il nuovo salvataggio :
{
"_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
"_class" : "com.baeldung.model.User",
"name" : "Jack"81*6
}
Ora eseguiamo l'operazione:
user = mongoTemplate.findOne(
Query.query(Criteria.where("name").is("Jack")), User.class);
user.setName("Jim");
userRepository.save(user);
Infine, ecco lo stato del database:
{
"_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
"_class" : "com.baeldung.model.User",
"name" : "Jim"
}
Nota ancora come salvare funziona con aggiornamento semantica perché stiamo usando un oggetto esistente.
6.4. Elimina
Ecco lo stato del database prima di chiamare delete :
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Benn"
}
Eseguiamo elimina :
userRepository.delete(user);
Ed ecco il nostro risultato:
{
}
6.5. Trova uno
Successivamente, questo è lo stato del database quando findOne si chiama:
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Chris"
}
Ora eseguiamo findOne :
userRepository.findOne(user.getId())
E il risultato restituirà i dati esistenti:
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Chris"
}
6.6. Esiste
Lo stato del database prima della chiamata esiste :
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Harris"
}
Ora eseguiamo exists , che ovviamente restituirà true :
boolean isExists = userRepository.exists(user.getId());
6.7. Trova tutto Con Ordina
Lo stato del database prima di chiamare findAll :
[
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Brendan"
},
{
"_id" : ObjectId("67b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Adam"
}
]
Ora eseguiamo findAll con Ordina :
List<User> users = userRepository.findAll(Sort.by(Sort.Direction.ASC, "name"));
Il risultato sarà ordinato per nome in ordine crescente :
[
{
"_id" : ObjectId("67b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Adam"
},
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Brendan"
}
]
6.8. Trova tutto Con Paginabile
Lo stato del database prima di chiamare findAll :
[
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Brendan"
},
{
"_id" : ObjectId("67b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Adam"
}
]
Ora eseguiamo findAll con una richiesta di impaginazione:
Pageable pageableRequest = PageRequest.of(0, 1);
Page<User> page = userRepository.findAll(pageableRequest);
List<User> users = pages.getContent();
Gli utenti risultanti list sarà un solo utente:
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Brendan"
}
7. Annotazioni
Infine, esaminiamo anche le semplici annotazioni che Spring Data utilizza per guidare queste operazioni API.
Il livello di campo @Id l'annotazione può decorare qualsiasi tipo, incluso lungo e stringa :
@Id
private String id;
Se il valore di @Id il campo non è nullo, è archiviato nel database così com'è; in caso contrario, il convertitore presumerà di voler memorizzare un ObjectId nel database (o ObjectId , Stringa oppure Intero grande lavoro).
Di seguito esamineremo @Document :
@Document
public class User {
//
}
Questa annotazione semplicemente contrassegna una classe come oggetto di dominio che deve essere mantenuto nel database, oltre a permetterci di scegliere il nome della raccolta da utilizzare.