Spring Boot MongoDB

Bienvenue dans l’exemple Spring Boot avec MongoDB. Spring Boot est le moyen le plus simple de démarrer rapidement un projet Spring, et MongoDB est la base de données NoSQL la plus populaire. Voyons comment intégrer Spring avec la base de données MongoDB.

Spring Boot MongoDB

Nous avons besoin des API suivantes pour travailler avec Spring Boot et la base de données MongoDB.

  • Spring Data MongoDB
  • Spring Boot

Il existe deux approches pour se connecter à la base de données MongoDB – MongoRepository et MongoTemplate. Nous essayerons de déterminer ce que chaque API offre par rapport à l’autre et quand vous devriez choisir l’une d’entre elles selon votre cas d’utilisation. Nous utiliserons l’outil Spring Initializr pour configurer rapidement le projet. Alors, commençons.

Configuration du projet Spring Boot MongoDB

Nous utiliserons l’outil Spring Initializr pour configurer rapidement le projet. Nous utiliserons simplement deux dépendances comme indiqué ci-dessous : Téléchargez le projet et décompressez-le. Importez-le ensuite dans votre IDE préféré – Eclipse ou IntelliJ IDEA.

Dépendances Maven

Bien que nous ayons déjà terminé la configuration avec l’outil, si vous souhaitez le configurer manuellement, nous utilisons le système de construction Maven pour ce projet et voici les dépendances que nous avons utilisées :

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.journaldev.spring</groupId>
	<artifactId>spring-boot-mongodb</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>spring-boot-mongodb</name>
	<description>Spring Boot MongoDB Example</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.5.9.RELEASE</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-mongodb</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>
</project>

Assurez-vous d’utiliser la version stable de Spring Boot depuis le référentiel Maven central.

Classe de modèle MongoDB Spring Boot

Nous avons une simple classe de modèle User.java.

package com.journaldev.bootifulmongodb.model;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;

@Document
public class User {

	@Id
	private String userId;
	private String name;
	private Date creationDate = new Date();
	private Map<String, String> userSettings = new HashMap<>();

	public String getUserId() {
		return userId;
	}

	public void setUserId(String userId) {
		this.userId = userId;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Date getCreationDate() {
		return creationDate;
	}

	public void setCreationDate(Date creationDate) {
		this.creationDate = creationDate;
	}

	public Map<String, String> getUserSettings() {
		return userSettings;
	}

	public void setUserSettings(Map<String, String> userSettings) {
		this.userSettings = userSettings;
	}
}

API MongoDB Spring Boot

Nous aurons les fonctionnalités suivantes et les interactions avec la base de données dans notre application.

  • Obtenir tous les utilisateurs
  • Obtenir un utilisateur par ID
  • Obtenir les paramètres de l’utilisateur
  • Obtenir une clé particulière de la carte
  • Ajouter/Mettre à jour les paramètres de l’utilisateur

Spring Data MongoDB – MongoRepository

Maintenant, nous utiliserons le référentiel Spring Data MongoDB pour accéder à nos données. Spring Data MongoRepository nous fournit des fonctionnalités communes que nous pouvons facilement brancher et utiliser. Définissons notre interface Repository.

package com.journaldev.bootifulmongodb.dal;

import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.stereotype.Repository;

import com.journaldev.bootifulmongodb.model.User;

@Repository
public interface UserRepository extends MongoRepository<User, String> {
}

Définition des propriétés MongoDB

Avant de définir notre contrôleur, il est important que nous établissions une connexion avec une instance locale de MongoDB. Nous utiliserons les propriétés Spring Boot pour cela.

# Configuration MongoDB locale
spring.data.mongodb.authentication-database=admin
spring.data.mongodb.username=root
spring.data.mongodb.password=root
spring.data.mongodb.database=user_db
spring.data.mongodb.port=27017
spring.data.mongodb.host=localhost

# Configuration de l'application
server.port=8102
spring.application.name=BootMongo
server.context-path=/user

Ainsi, l’application s’exécutera sur le port 8102 et se connectera à une instance locale de MongoDB avec les identifiants fournis. Si vous avez une instance locale sans autorisation activée, vous pouvez simplement supprimer les trois premières lignes de configuration.

Définition du contrôleur Spring

Passons enfin à la création de notre classe Controller.

package com.journaldev.bootifulmongodb.controller;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.journaldev.bootifulmongodb.dal.UserRepository;
import com.journaldev.bootifulmongodb.model.User;

@RestController
@RequestMapping(value = "/")
public class UserController {

	private final Logger LOG = LoggerFactory.getLogger(getClass());

	private final UserRepository userRepository;

	public UserController(UserRepository userRepository) {
		this.userRepository = userRepository;
	}
}

Nous venons de autowirer la dépendance de l’interface du référentiel et nous l’utiliserons ensuite.

Définition des APIs

Pour les fonctionnalités que nous avons mentionnées, nous allons maintenant créer des APIs et accéder à la dépendance du référentiel utilisateur qui utilisera internement l’API Spring Data MongoRepository. Remarquez que nous n’avons pas besoin d’écrire de code d’interaction avec la base de données dans l’interface, car Spring Data le fait tout pour nous.

Obtenir tous les utilisateurs

@RequestMapping(value = "", method = RequestMethod.GET)
public List<User> getAllUsers() {
	LOG.info("Getting all users.");
	return userRepository.findAll();
}

findAll() est juste une méthode que Spring Data MongoRepository fournit en interne.

Obtenir un utilisateur par ID

Maintenant, essayons d’obtenir un utilisateur spécifique avec un ID.

@RequestMapping(value = "/{userId}", method = RequestMethod.GET)
public User getUser(@PathVariable String userId) {
	LOG.info("Getting user with ID: {}.", userId);
	return userRepository.findOne(userId);
}

findOne() est juste une méthode que Spring Data MongoRepository fournit en interne pour obtenir un objet par un ID.

Ajouter un nouvel utilisateur

Nous allons ajouter un nouvel utilisateur dans la fonction ci-dessous.

@RequestMapping(value = "/create", method = RequestMethod.POST)
public User addNewUsers(@RequestBody User user) {
	LOG.info("Saving user.");
	return userRepository.save(user);
}

Obtenir les paramètres de l’utilisateur

Maintenant que nous avons ajouté des données d’exemple dans la base de données, essayons d’en extraire une partie.

@RequestMapping(value = "/settings/{userId}", method = RequestMethod.GET)
public Object getAllUserSettings(@PathVariable String userId) {
	User user = userRepository.findOne(userId);
	if (user != null) {
		return user.getUserSettings();
	} else {
		return "User not found.";
	}
}

Obtenir un paramètre particulier de l’utilisateur

@RequestMapping(value = "/settings/{userId}/{key}", method = RequestMethod.GET)
public String getUserSetting(@PathVariable String userId, @PathVariable String key) {
	User user = userRepository.findOne(userId);
	if (user != null) {
		return user.getUserSettings().get(key);
	} else {
		return "User not found.";
	}
}

Remarquez dans la requête ci-dessus, nous avons obtenu l’objet utilisateur, puis extrait la carte de paramètres complète (qui aurait pu contenir des milliers d’objets) et enfin obtenu notre propre valeur. C’est un inconvénient pour la requête Spring Data lorsque nous l’utilisons comme API directe.

Ajouter un nouveau paramètre utilisateur

Essayons d’ajouter des données à un utilisateur existant:

@RequestMapping(value = "/settings/{userId}/{key}/{value}", method = RequestMethod.GET)
public String addUserSetting(@PathVariable String userId, @PathVariable String key, @PathVariable String value) {
	User user = userRepository.findOne(userId);
	if (user != null) {
		user.getUserSettings().put(key, value);
		userRepository.save(user);
		return "Key added";
	} else {
		return "User not found.";
	}
}

Avec tout le code que nous avons écrit, il est clair que nous n’avons pas eu à écrire une seule ligne de code pour accéder à la base de données en dehors de la définition de l’interface de référentiel et de l’autocâblage de la dépendance. C’est la facilité que nous offre l’API Spring Data MongoRepository, mais elle a aussi quelques inconvénients. Nous les élaborerons lorsque nous aurons également défini la version de MongoTemplate. Commençons également par cela.

Spring Data MongoDB – MongoTemplate

Nous allons définir ici les requêtes de base de données MongoTemplate. Avec MongoTemplate, vous verrez que nous avons beaucoup plus de contrôle granulaire sur ce que nous interrogeons et quelles données sont incluses dans les résultats.

Définition de l’interface DAL

Pour fournir un contrat au niveau d’accès à la base de données, nous commencerons par définir une interface qui fonctionne exactement comme nos méthodes intégrées de Spring Data.

package com.journaldev.bootifulmongodb.dal;

import java.util.List;

import com.journaldev.bootifulmongodb.model.User;

public interface UserDAL {

	List<User> getAllUsers();

	User getUserById(String userId);

	User addNewUser(User user);

	Object getAllUserSettings(String userId);

	String getUserSetting(String userId, String key);

	String addUserSetting(String userId, String key, String value);
}

Implémentation de l’interface DAL

Passons maintenant à la définition de ces méthodes.

package com.journaldev.bootifulmongodb.dal;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Repository;

import com.journaldev.bootifulmongodb.model.User;

@Repository
public class UserDALImpl implements UserDAL {

	@Autowired
	private MongoTemplate mongoTemplate;

	@Override
	public List getAllUsers() {
		return mongoTemplate.findAll(User.class);
	}

	@Override
	public User getUserById(String userId) {
		Query query = new Query();
		query.addCriteria(Criteria.where("userId").is(userId));
		return mongoTemplate.findOne(query, User.class);
	}

	@Override
	public User addNewUser(User user) {
		mongoTemplate.save(user);
		// Maintenant, l'objet utilisateur contiendra également l'identifiant
		return user;
	}

	@Override
	public Object getAllUserSettings(String userId) {
		Query query = new Query();
		query.addCriteria(Criteria.where("userId").is(userId));
		User user = mongoTemplate.findOne(query, User.class);
		return user != null ? user.getUserSettings() : "User not found.";
	}

	@Override
	public String getUserSetting(String userId, String key) {
		Query query = new Query();
		query.fields().include("userSettings");
		query.addCriteria(Criteria.where("userId").is(userId).andOperator(Criteria.where("userSettings." + key).exists(true)));
		User user = mongoTemplate.findOne(query, User.class);
		return user != null ? user.getUserSettings().get(key) : "Not found.";
	}

	@Override
	public String addUserSetting(String userId, String key, String value) {
		Query query = new Query();
		query.addCriteria(Criteria.where("userId").is(userId));
		User user = mongoTemplate.findOne(query, User.class);
		if (user != null) {
			user.getUserSettings().put(key, value);
			mongoTemplate.save(user);
			return "Key added.";
		} else {
			return "User not found.";
		}
	}
}

Les implémentations de méthode dans la classe ci-dessus utilisent la dépendance MongoTemplate. Voyez comment la méthode getUserById(...) obtient l’utilisateur. Nous construisons une requête et passons les paramètres requis. Ce qui vous intéressera davantage, c’est la requête getUserSetting. Essayons de comprendre ce qui s’est passé ci-dessus:

  • Nous avons construit des requêtes avec des critères pour vérifier l’égalité.
  • La méthode include inclut les noms de champs que le résultat devrait inclure lorsqu’il est extrait de la base de données. Cela signifie que, dans ce cas, la clé userSettings sera extraite, ce qui permettra d’économiser beaucoup de données à récupérer qui ne sont pas nécessaires
  • Nous avons également fait une requête sur à la fois l’utilisateur et la clé de la carte. Si l’un d’eux n’est pas trouvé, nous renvoyons des données vides, ce qui signifie que la clé requise n’a pas été trouvée. Cela évite même de récupérer l’objet Utilisateur du tout si la clé requise n’était pas présente

Test d’exécution Spring Data MongoDB

Nous pouvons exécuter cette application simplement en utilisant une seule commande :

mvn spring-boot:run

Une fois l’application en cours d’exécution, nous pouvons essayer de sauvegarder un nouvel utilisateur en utilisant cette API :

https://localhost:8102/user/create

Comme il s’agira d’une requête POST, nous enverrons également des données JSON :

{
  "name" : "Shubham",
  "userSettings" : {
    "bike" : "pulsar"
  }
}

Comme nous retournons la réponse Mongo elle-même, nous obtiendrons quelque chose comme :

{
  "userId": "5a5f28cc3178058b0fafe1dd",
  "name": "Shubham",
  "creationDate": 1516165830856,
  "userSettings": {
    "bike" : "pulsar"
  }
}

Vous pouvez obtenir tous les utilisateurs en utilisant l’API comme requête GET :

https://localhost:8102/user/

Nous obtiendrons quelque chose comme :

[
  {
    "userId": "5a5f28cc3178058b0fafe1dd",
    "name": "Shubham",
    "creationDate": 1516165830856,
    "userSettings": {
      "bike" : "pulsar"
    }
  }
]

Si vous regardez la classe UserController ci-dessus, nous n’avons pas connecté MongoTemplate à utiliser. Le code ci-dessous montre les modifications nécessaires pour utiliser MongoTemplate pour lire les paramètres utilisateur.

//définir l'objet de couche d'accès aux données
private final UserDAL userDAL;

//initialiser l'objet DAL via l'autocâblage du constructeur
public UserController(UserRepository userRepository, UserDAL userDAL) {
	this.userRepository = userRepository;
	this.userDAL = userDAL;
}

//modifier l'implémentation de la méthode pour utiliser DAL et donc MongoTemplate
@RequestMapping(value = "/settings/{userId}", method = RequestMethod.GET)
public Object getAllUserSettings(@PathVariable String userId) {
    User user = userRepository.findOne(userId);
    if (user != null) {
        return userDAL.getAllUserSettings(userId);
    } else {
        return "User not found.";
    }
}

//modifier l'implémentation de la méthode pour utiliser DAL et donc MongoTemplate
@RequestMapping(value = "/settings/{userId}/{key}", method = RequestMethod.GET)
public String getUserSetting(
        @PathVariable String userId, @PathVariable String key) {
    return userDAL.getUserSetting(userId, key);
}

Redémarrez l’application et exécutez des scénarios pour obtenir tous les paramètres utilisateur et pour obtenir une clé spécifique. L’image ci-dessous montre la sortie de l’application Postman.

MongoTemplate vs MongoRepository

  • MongoTemplate offre beaucoup plus de contrôle en ce qui concerne la requête de données et les données à extraire de la base de données.
  • Les référentiels Spring Data nous offrent une vue pratique de la façon de récupérer des données.
  • MongoTemplate dépend de la base de données. Cela signifie que, avec les référentiels Spring Data, vous pouvez facilement passer à une base de données différente en utilisant simplement des référentiels Spring Data différents pour MySQL ou Neo4J ou tout autre chose. Ce n’est pas possible avec MongoTemplate.

Résumé de Spring Boot MongoDB

Dans cette leçon, nous avons examiné comment MongoTemplate peut nous offrir plus de contrôle sur les dépôts de données Spring, mais cela peut aussi devenir un peu compliqué lorsque des requêtes plus approfondies sont impliquées. Ainsi, c’est entièrement à vous de choisir ce que vous souhaitez lorsque vous développez votre idée. N’hésitez pas à laisser des commentaires ci-dessous. Téléchargez le code source à partir du lien ci-dessous. Veuillez vous assurer de modifier les informations d’identification MongoDB avant d’exécuter l’application fournie.

Télécharger le projet exemple Spring Boot MongoDB

Source:
https://www.digitalocean.com/community/tutorials/spring-boot-mongodb