1. Présentation
Cet article sera une introduction rapide et pratique à Spring Data MongoDB.
Nous allons passer en revue les bases en utilisant à la fois le MongoTemplate ainsi que MongoRepository , avec des exemples pratiques pour illustrer chaque opération.
Pour en savoir plus :
Support géospatial dans MongoDB
Découvrez comment stocker, indexer et rechercher des données géospatiales avec MongoDBEn savoir plus →Test d'intégration Spring Boot avec MongoDB intégré
Apprenez à utiliser la solution MongoDB intégrée de Flapdoodle avec Spring Boot pour exécuter les tests d'intégration MongoDB en douceur.En savoir plus →2. Modèle Mongo et MongoRepository
Le Modèle Mongo suit le modèle de modèle standard de Spring et fournit une API de base prête à l'emploi au moteur de persistance sous-jacent.
Le référentiel suit l'approche centrée sur Spring Data et propose des opérations d'API plus flexibles et complexes, basées sur les modèles d'accès bien connus dans tous les projets Spring Data.
Pour les deux, nous devons commencer par définir la dépendance — par exemple, dans le pom.xml , avec Maven :
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>3.0.3.RELEASE</version>
</dependency>
Pour vérifier si une nouvelle version de la bibliothèque a été publiée, suivez les versions ici.
3. Configuration pour MongoTemplate
3.1. Configuration XML
Commençons par la configuration XML simple du modèle Mongo :
<mongo:mongo-client id="mongoClient" host="localhost" />
<mongo:db-factory id="mongoDbFactory" dbname="test" mongo-client-ref="mongoClient" />
Nous devons d'abord définir le bean d'usine responsable de la création des instances Mongo.
Ensuite, nous devons réellement définir (et configurer) le bean modèle :
<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
<constructor-arg ref="mongoDbFactory"/>
</bean>
Et enfin, nous devons définir un post-processeur pour traduire toutes les MongoExceptions jeté dans @Repository classes annotées :
<bean class=
"org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
3.2. Paramétrage Java
Créons maintenant une configuration similaire à l'aide de la configuration Java en étendant la classe de base pour la configuration 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");
}
}
Notez que nous n'avons pas eu besoin de définir MongoTemplate bean dans la configuration précédente puisqu'il est déjà défini dans AbstractMongoClientConfiguration .
Nous pouvons également utiliser notre configuration à partir de zéro sans étendre 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. Configuration pour MongoRepository
4.1. Configuration XML
Pour utiliser des référentiels personnalisés (en étendant le MongoRepository ), nous devons continuer la configuration à partir de la section 3.1. et configurez les référentiels :
<mongo:repositories
base-package="com.baeldung.repository" mongo-template-ref="mongoTemplate"/>
4.2. Paramétrage Java
De même, nous allons construire sur la configuration que nous avons déjà créée dans la section 3.2. et ajoutez une nouvelle annotation au mix :
@EnableMongoRepositories(basePackages = "com.baeldung.repository")
4.3. Créer le référentiel
Après la configuration, nous devons créer un référentiel — en étendant le MongoRepository existant interface :
public interface UserRepository extends MongoRepository<User, String> {
//
}
Maintenant, nous pouvons connecter automatiquement ce UserRepository et utiliser les opérations de MongoRepository ou ajouter des opérations personnalisées.
5. Utiliser MongoTemplate
5.1. Insérer
Commençons par l'opération d'insertion ainsi qu'une base de données vide :
{
}
Maintenant, si nous insérons un nouvel utilisateur :
User user = new User();
user.setName("Jon");
mongoTemplate.insert(user, "user");
la base de données ressemblera à ceci :
{
"_id" : ObjectId("55b4fda5830b550a8c2ca25a"),
"_class" : "com.baeldung.model.User",
"name" : "Jon"
}
5.2. Enregistrer – Insérer
La sauvegarde l'opération a une sémantique de sauvegarde ou de mise à jour :si un identifiant est présent, elle effectue une mise à jour, et sinon, elle effectue une insertion.
Regardons la première sémantique - l'insertion.
Voici l'état initial de la base de données :
{
}
Quand maintenant nous sauvons un nouvel utilisateur :
User user = new User();
user.setName("Albert");
mongoTemplate.save(user, "user");
l'entité sera insérée dans la base de données :
{
"_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
"_class" : "com.baeldung.model.User",
"name" : "Albert"
}
Ensuite, nous examinerons la même opération :enregistrer — avec sémantique de mise à jour.
5.3. Enregistrer – Mettre à jour
Regardons maintenant enregistrer avec sémantique de mise à jour, opérant sur une entité existante :
{
"_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
"_class" : "com.baeldung.model.User",
"name" : "Jack"
}
Quand nous économisons l'utilisateur existant, nous le mettrons à jour :
user = mongoTemplate.findOne(
Query.query(Criteria.where("name").is("Jack")), User.class);
user.setName("Jim");
mongoTemplate.save(user, "user");
La base de données ressemblera à ceci :
{
"_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
"_class" : "com.baeldung.model.User",
"name" : "Jim"
}
Nous pouvons voir que dans cet exemple particulier, save utilise la sémantique de update parce que nous utilisons un objet avec _id donné .
5.4. Mettre à jour d'abord
mettre à jour d'abord met à jour le tout premier document qui correspond à la requête.
Commençons par l'état initial de la base :
[
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Alex"
},
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614c"),
"_class" : "com.baeldung.model.User",
"name" : "Alex"
}
]
Lorsque nous exécutons maintenant le 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);
seule la première entrée sera mise à jour :
[
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "James"
},
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614c"),
"_class" : "com.baeldung.model.User",
"name" : "Alex"
}
]
5.5. Mise à jour multiple
Mise à jour multiple met à jour tous les documents qui correspondent à la requête donnée.
Tout d'abord, voici l'état de la base de données avant de faire le updateMulti :
[
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Eugen"
},
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614c"),
"_class" : "com.baeldung.model.User",
"name" : "Eugen"
}
]
Maintenant, lançons le updateMulti opération :
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);
Les deux objets existants seront mis à jour dans la base de données :
[
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Victor"
},
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614c"),
"_class" : "com.baeldung.model.User",
"name" : "Victor"
}
]
5.6. RechercherEtModifier
Cette opération fonctionne comme updateMulti , mais il renvoie l'objet avant sa modification.
Tout d'abord, voici l'état de la base de données avant d'appeler findAndModify :
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Markus"
}
Regardons le code d'opération réel :
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'objet utilisateur renvoyé a les mêmes valeurs que l'état initial dans la base de données.
Cependant, voici le nouvel état dans la base de données :
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Nick"
}
5.7. Insérer
Le upsert fonctionne sur la recherche et modification sinon créer la sémantique :si le document correspond, mettez-le à jour, ou bien créez un nouveau document en combinant l'objet requête et mise à jour.
Commençons par l'état initial de la base :
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Markus"
}
Exécutons maintenant le 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);
Voici l'état de la base de données après l'opération :
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Nick"
}
5.8. Supprimer
Nous examinerons l'état de la base de données avant d'appeler supprimer :
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Benn"
}
Exécutons maintenant supprimer :
mongoTemplate.remove(user, "user");
Le résultat sera comme prévu :
{
}
6. Utilisation de MongoRepository
6.1. Insérer
Tout d'abord, nous verrons l'état de la base de données avant d'exécuter l'insert :
{
}
Nous allons maintenant insérer un nouvel utilisateur :
User user = new User();
user.setName("Jon");
userRepository.insert(user);
Et voici l'état final de la base de données :
{
"_id" : ObjectId("55b4fda5830b550a8c2ca25a"),
"_class" : "com.baeldung.model.User",
"name" : "Jon"
}
Notez comment l'opération fonctionne de la même manière que l'insert dans le MongoTemplate API.
6.2. Enregistrer – Insérer
De même, enregistrez fonctionne de la même manière que la sauvegarde opération dans le MongoTemplate API.
Commençons par examiner la sémantique de l'insertion de l'opération.
Voici l'état initial de la base de données :
{
}
Maintenant, nous exécutons la save opération :
User user = new User();
user.setName("Aaron");
userRepository.save(user);
Cela entraîne l'ajout de l'utilisateur à la base de données :
{
"_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
"_class" : "com.baeldung.model.User",
"name" : "Aaron"
}
Notez à nouveau comment économiser fonctionne avec insérer sémantique car nous insérons un nouvel objet.
6.3. Enregistrer – Mettre à jour
Regardons maintenant la même opération mais avec la sémantique de mise à jour.
Tout d'abord, voici l'état de la base de données avant d'exécuter la nouvelle save :
{
"_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
"_class" : "com.baeldung.model.User",
"name" : "Jack"81*6
}
Maintenant, nous exécutons l'opération :
user = mongoTemplate.findOne(
Query.query(Criteria.where("name").is("Jack")), User.class);
user.setName("Jim");
userRepository.save(user);
Enfin, voici l'état de la base de données :
{
"_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
"_class" : "com.baeldung.model.User",
"name" : "Jim"
}
Notez à nouveau comment économiser fonctionne avec mise à jour sémantique car nous utilisons un objet existant.
6.4. Supprimer
Voici l'état de la base de données avant d'appeler supprimer :
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Benn"
}
Exécutons supprimer :
userRepository.delete(user);
Et voici notre résultat :
{
}
6.5. FindOne
Ensuite, voici l'état de la base de données lorsque findOne s'appelle :
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Chris"
}
Exécutons maintenant le findOne :
userRepository.findOne(user.getId())
Et le résultat renverra les données existantes :
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Chris"
}
6.6. Existe
L'état de la base de données avant d'appeler existe :
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Harris"
}
Maintenant, lançons exists , qui renverra bien sûr true :
boolean isExists = userRepository.exists(user.getId());
6.7. Rechercher tout Avec Trier
L'état de la base de données avant d'appeler findAll :
[
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Brendan"
},
{
"_id" : ObjectId("67b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Adam"
}
]
Lançons maintenant findAll avecTrier :
List<User> users = userRepository.findAll(Sort.by(Sort.Direction.ASC, "name"));
Le résultat sera trié par nom dans l'ordre croissant :
[
{
"_id" : ObjectId("67b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Adam"
},
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Brendan"
}
]
6.8. Rechercher tout Avec Pageable
L'état de la base de données avant d'appeler findAll :
[
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Brendan"
},
{
"_id" : ObjectId("67b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Adam"
}
]
Exécutons maintenant findAll avec une requête de pagination :
Pageable pageableRequest = PageRequest.of(0, 1);
Page<User> page = userRepository.findAll(pageableRequest);
List<User> users = pages.getContent();
Les utilisateurs résultants la liste ne comportera qu'un seul utilisateur :
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Brendan"
}
7. Annotations
Enfin, passons également en revue les annotations simples que Spring Data utilise pour piloter ces opérations d'API.
Le niveau de champ @Id l'annotation peut décorer n'importe quel type, y compris long et chaîne :
@Id
private String id;
Si la valeur de @Id le champ n'est pas nul, il est stocké tel quel dans la base de données ; sinon, le convertisseur supposera que nous voulons stocker un ObjectId dans la base de données (soit ObjectId , Chaîne ou BigInteger travail).
Nous allons ensuite examiner @Document :
@Document
public class User {
//
}
Cette annotation marque simplement une classe comme étant un objet de domaine qui doit être conservé dans la base de données, tout en nous permettant de choisir le nom de la collection à utiliser.