Introduction à Spring Data MongoDB

Introduction à Spring Data MongoDB

1. Vue d'ensemble

Cet article sera unintroduction to Spring Data MongoDB rapide et pratique.

Nous allons passer en revue les bases en utilisant à la fois lesMongoTemplate et lesMongoRepository en utilisant des exemples pratiques pour illustrer chaque opération.

Lectures complémentaires:

Support géospatial dans MongoDB

Découvrez comment stocker, indexer et rechercher des données géospatiales avec MongoDB

Read more

Test d'intégration de démarrage Spring avec Embedded MongoDB

Découvrez comment utiliser la solution MongoDB intégrée de Flapdoodle avec Spring Boot pour exécuter les tests d'intégration MongoDB en douceur.

Read more

2. MongoTemplateand MongoRepository

The MongoTemplate 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.

The repository suit l'approche centrée sur Spring Data et est livré avec 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 lespom.xml, avec Maven:


    org.springframework.data
    spring-data-mongodb
    2.1.9.RELEASE



    org.springframework.data
    spring-data-releasetrain
    Lovelace-SR9
    pom
    import

Pour vérifier si une nouvelle version de la bibliothèque a été publiée -track the releases here.

3. Configuration pourMongoTemplate

3.1. Configuration XML

Commençons par la configuration XML simple pour le modèle Mongo:


Premièrement, nous devons définir le bean factory responsable de la création d'instances Mongo.

Ensuite, nous devons définir (et configurer) le bean template:


    

Et enfin, nous devons définir un post-processeur pour traduire toutMongoExceptions jeté dans les classes annotées@Repository:

3.2. Configuration Java

Créons maintenant une configuration similaire à l’aide de la configuration Java en étendant la classe de base pour la configuration MongoDBAbstractMongoConfiguration:

@Configuration
public class MongoConfig extends AbstractMongoConfiguration {

    @Override
    protected String getDatabaseName() {
        return "test";
    }

    @Override
    public MongoClient mongoClient() {
        return new MongoClient("127.0.0.1", 27017);
    }

    @Override
    protected String getMappingBasePackage() {
        return "org.example";
    }
}

Remarque: nous n'avons pas eu besoin de définir le beanMongoTemplate dans la configuration précédente car il est déjà défini dansAbstractMongoConfiguration

Nous pouvons également utiliser notre configuration à partir de zéro sans étendreAbstractMongoConfiguration - comme suit:

@Configuration
public class SimpleMongoConfig {

    @Bean
    public MongoClient mongo() {
        return new MongoClient("localhost");
    }

    @Bean
    public MongoTemplate mongoTemplate() throws Exception {
        return new MongoTemplate(mongo(), "test");
    }
}

4. Configuration pourMongoRepository

4.1. Configuration XML

Pour utiliser des référentiels personnalisés (étendre lesMongoRepository) - nous devons continuer la configuration de la section 3.1 et configurer les référentiels:

4.2. Configuration Java

De même, nous allons construire sur la configuration que nous avons déjà créée dans la section 3.2 et ajouter une nouvelle annotation dans le mix:

@EnableMongoRepositories(basePackages = "org.example.repository")

4.3. Créer le référentiel

Maintenant, après la configuration, nous devons créer un référentiel - étendant l'interface existante deMongoRepository:

public interface UserRepository extends MongoRepository {
    //
}

Nous pouvons maintenant câbler automatiquement ceUserRepository et utiliser les opérations deMongoRepository ou ajouter des opérations personnalisées.

5. Utilisation deMongoTemplate

5.1. Insert

Commençons par l'opération d'insertion; Commençons également avec 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" : "org.example.model.User",
    "name" : "Jon"
}

5.2. Save – Insert

L'opérationsave a une sémantique de sauvegarde ou de mise à jour: si un id est présent, elle effectue une mise à jour, sinon - elle fait une insertion.

Regardons la première sémantique - l’insert; voici l’état initial de la base de données:

{
}

Quand nous sommes maintenantsaveun 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" : "org.example.model.User",
    "name" : "Albert"
}

Ensuite, nous examinerons la même opération -save - avec la sémantique de mise à jour.

5.3. Save – Update

Examinons maintenantsave avec une sémantique de mise à jour, fonctionnant sur une entité existante:

{
    "_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
    "_class" : "org.example.model.User",
    "name" : "Jack"
}

Maintenant, quand noussave 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" : "org.example.model.User",
    "name" : "Jim"
}

Comme vous pouvez le voir, dans cet exemple particulier,save utilise la sémantique deupdate, car nous utilisons un objet avec des_id donnés.

5.4. UpdateFirst

updateFirst met à jour le tout premier document correspondant à la requête.

Commençons par l'état initial de la base de données:

[
    {
        "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
        "_class" : "org.example.model.User",
        "name" : "Alex"
    },
    {
        "_id" : ObjectId("55b5ffa5511fee0e45ed614c"),
        "_class" : "org.example.model.User",
        "name" : "Alex"
    }
]

Lorsque nous exécutons maintenant lesupdateFirst:

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" : "org.example.model.User",
        "name" : "James"
    },
    {
        "_id" : ObjectId("55b5ffa5511fee0e45ed614c"),
        "_class" : "org.example.model.User",
        "name" : "Alex"
    }
]

5.5. UpdateMulti

UpdateMultiupdates all document that matches the given query.

Tout d'abord, voici l'état de la base de données avant d'effectuer lesupdateMulti:

[
    {
        "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
        "_class" : "org.example.model.User",
        "name" : "Eugen"
    },
    {
        "_id" : ObjectId("55b5ffa5511fee0e45ed614c"),
        "_class" : "org.example.model.User",
        "name" : "Eugen"
    }
]

Maintenant, exécutons l'opérationupdateMulti:

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" : "org.example.model.User",
        "name" : "Victor"
    },
    {
        "_id" : ObjectId("55b5ffa5511fee0e45ed614c"),
        "_class" : "org.example.model.User",
        "name" : "Victor"
    }
]

5.6. FindAndModify

Cette opération fonctionne commeupdateMulti, mais ellereturns the object before it was modified.

Premièrement - l'état de la base de données avant d'appelerfindAndModify:

{
    "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
    "_class" : "org.example.model.User",
    "name" : "Markus"
}

Examinons 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);

Leuser object renvoyé a les mêmes valeurs que l'état initial dans la base de données.

Cependant, le nouvel état dans la base de données est:

{
    "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
    "_class" : "org.example.model.User",
    "name" : "Nick"
}

5.7. Upsert

Les travaux deupsert opèrent sur lesfind and modify else create semantics: si le document est mis en correspondance, mettez-le à jour, sinon créez un nouveau document en combinant l'objet de requête et de mise à jour.

Commençons par l'état initial de la base de données:

{
    "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
    "_class" : "org.example.model.User",
    "name" : "Markus"
}

Maintenant, exécutons lesupsert:

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" : "org.example.model.User",
    "name" : "Nick"
}

5.8. Remove

L'état de la base de données avant d'appelerremove:

{
    "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
    "_class" : "org.example.model.User",
    "name" : "Benn"
}

Exécutons maintenantremove:

mongoTemplate.remove(user, "user");

Le résultat sera comme prévu:

{
}

6. Utilisation deMongoRepository

6.1. Insert

First - l'état de la base de données avant d'exécuter lesinsert:

{
}

Maintenant, quand on insère un nouvel utilisateur:

User user = new User();
user.setName("Jon");
userRepository.insert(user);

Voici l'état final de la base de données:

{
    "_id" : ObjectId("55b4fda5830b550a8c2ca25a"),
    "_class" : "org.example.model.User",
    "name" : "Jon"
}

Notez comment l'opération fonctionne de la même manière que lesinsert dans l'APIMongoTemplate.

6.2. Save -Insert

De même -save fonctionne de la même manière que l'opérationsave dans l'APIMongoTemplate.

Commençons par regarderthe insert semantics de l'opération; voici l’état initial de la base de données:

{
}

Maintenant - nous exécutons l'opérationsave:

User user = new User();
user.setName("Aaron");
userRepository.save(user);

Cela se traduit par l'ajout de l'utilisateur à la base de données:

{
    "_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
    "_class" : "org.example.model.User",
    "name" : "Aaron"
}

Notez à nouveau comment, dans cet exemple,save fonctionne avec la sémantique deinsert, car nous insérons un nouvel objet.

6.3. Save -Update

Regardons maintenant la même opération mais avecupdate semantics.

Tout d'abord - voici l'état de la base de données avant d'exécuter les nouveauxsave:

{
    "_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
    "_class" : "org.example.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" : "org.example.model.User",
    "name" : "Jim"
}

Notez à nouveau comment, dans cet exemple,save fonctionne avec la sémantique deupdate, car nous utilisons un objet existant.

6.4. Delete

L'état de la base de données avant d'appelerdelete:

{
    "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
    "_class" : "org.example.model.User",
    "name" : "Benn"
}

Lançonsdelete:

userRepository.delete(user);

Le résultat sera simplement:

{
}

6.5. FindOne

L'état de la base de données lorsquefindOne est appelé:

{
    "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
    "_class" : "org.example.model.User",
    "name" : "Chris"
}

Exécutons maintenant lesfindOne:

userRepository.findOne(user.getId())

Le résultat qui retournera les données existantes:

{
    "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
    "_class" : "org.example.model.User",
    "name" : "Chris"
}

6.6. Exists

L'état de la base de données avant d'appelerexists:

{
    "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
    "_class" : "org.example.model.User",
    "name" : "Harris"
}

Maintenant, exécutonsexists:

boolean isExists = userRepository.exists(user.getId());

Ce qui renverra bien sûrtrue.

6.7. FindAll #with[.pl-en] Sort#

L'état de la base de données avant d'appelerfindAll:

[
    {
        "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
        "_class" : "org.example.model.User",
        "name" : "Brendan"
    },
    {
       "_id" : ObjectId("67b5ffa5511fee0e45ed614b"),
       "_class" : "org.example.model.User",
       "name" : "Adam"
    }
]

Exécutons maintenantfindAll avecSort:

List users = userRepository.findAll(new Sort(Sort.Direction.ASC, "name"));

Le résultat serasorted by name in ascending order:

[
    {
        "_id" : ObjectId("67b5ffa5511fee0e45ed614b"),
        "_class" : "org.example.model.User",
        "name" : "Adam"
    },
    {
        "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
        "_class" : "org.example.model.User",
        "name" : "Brendan"
    }
]

6.8. FindAll #with[.pl-en] Pageable #

L'état de la base de données avant d'appelerfindAll:

[
    {
        "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
        "_class" : "org.example.model.User",
        "name" : "Brendan"
    },
    {
        "_id" : ObjectId("67b5ffa5511fee0e45ed614b"),
        "_class" : "org.example.model.User",
        "name" : "Adam"
    }
]

Exécutons maintenantfindAll avec une requête de pagination:

Pageable pageableRequest = PageRequest.of(0, 1);
Page page = userRepository.findAll(pageableRequest);
List users = pages.getContent();

La liste desusers résultante sera un seul utilisateur: __

{
    "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
    "_class" : "org.example.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.

@Id
private String id;

L'annotation de niveau de champ@Id peut décorer n'importe quel type, y comprislong etstring.

Si la valeur du champ@Id n’est pas nulle, il est stocké tel quel dans la base de données; sinon, le convertisseur supposera que vous voulez stocker unObjectId dans la base de données (soitObjectId, String soitBigInteger travail).

Suivant -@Document:

@Document
public class User {
    //
}

Cette annotation est simplementmarks a class as being a domain object qui doit être conservée dans la base de données, tout en nous permettant de choisir le nom de la collection à utiliser.

8. Conclusion

Cet article était une introduction rapide mais complète à l'utilisation de MongoDB avec Spring Data, à la fois via l'APIMongoTemplate et en utilisantMongoRepository.

L'implémentation de tous ces exemples et extraits de codecan be foundover on Github - il s'agit d'un projet basé sur Maven, il devrait donc être facile à importer et à exécuter tel quel.