Spring Boot MongoDB

Benvenuti all’esempio di Spring Boot MongoDB. Spring Boot è il modo più semplice per avviare rapidamente un progetto spring e MongoDB è il database NoSQL più popolare. Vediamo come integrare Spring con il database MongoDB.

Spring Boot MongoDB

Avere bisogno delle seguenti API per lavorare con Spring Boot e il database MongoDB.

  • Spring Data MongoDB
  • Spring Boot

Ci sono due approcci attraverso i quali possiamo connetterci al database MongoDB – MongoRepository e MongoTemplate. Cercheremo di stabilire cosa offre una API rispetto all’altra e quando dovresti scegliere una qualsiasi di esse per il tuo caso d’uso. Faremo uso dello strumento Spring Initializr per impostare rapidamente il progetto. Quindi, iniziamo.

Configurazione del progetto Spring Boot MongoDB

Faremo uso dello strumento Spring Initializr per impostare rapidamente il progetto. Utilizzeremo solo due dipendenze come mostrato di seguito: Scarica il progetto e scompattalo. Quindi importalo nel tuo IDE preferito – Eclipse o IntelliJ IDEA.

Dipendenze di Maven

Anche se abbiamo già completato la configurazione con lo strumento, se desideri configurarlo manualmente, utilizziamo il sistema di compilazione Maven per questo progetto ed ecco le dipendenze che abbiamo utilizzato:

<?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>

Assicurati di utilizzare la versione stabile per Spring Boot dal repository Maven centrale.

Classe del modello MongoDB di Spring Boot

Abbiamo una semplice classe di modello 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 di MongoDB di Spring Boot

Avremo le seguenti funzionalità e interazioni con il database nella nostra app.

  • Ottenere tutti gli utenti
  • Ottenere un utente con ID
  • Ottenere impostazioni utente
  • Ottenere una chiave particolare dalla mappa
  • Aggiungere/Aggiornare impostazioni utente

Spring Data MongoDB – MongoRepository

Ora utilizzeremo il repository Spring Data MongoDB per accedere ai nostri dati. Spring Data MongoRepository ci fornisce funzionalità comuni che possiamo facilmente integrare e utilizzare. Definiamo la nostra interfaccia 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> {
}

Definizione delle proprietà MongoDB

Prima di impostare il nostro controller, è importante che stabiliamo una connessione con un’istanza locale di MongoDB. Utilizzeremo le proprietà di Spring Boot per farlo.

# Configurazione 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

# Configurazione dell'applicazione
server.port=8102
spring.application.name=BootMongo
server.context-path=/user

Quindi, l’applicazione verrà eseguita sulla porta 8102 e si collegherà a un’istanza locale di MongoDB con le credenziali fornite. Se si dispone di un’istanza locale senza autorizzazione abilitata, è sufficiente rimuovere le prime tre righe di configurazione.

Definizione del controller Spring

Passiamo infine alla creazione della nostra 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;
	}
}

Abbiamo appena Autowired la dipendenza dell’interfaccia del repository e la utilizzeremo successivamente.

Definizione delle API

Per le funzionalità che abbiamo menzionato, ora creeremo le API e accederemo alla dipendenza dell’utente del repository che utilizzerà internamente l’API Spring Data MongoRepository. Nota che non dobbiamo scrivere alcun codice di interazione con il database nell’interfaccia poiché Spring Data lo fa tutto per noi.

Ottenere tutti gli utenti

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

findAll() è solo un metodo che Spring Data MongoRepository fornisce internamente.

Ottenere un utente per ID

Adesso, cerchiamo di ottenere un utente specifico con 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() è solo un metodo che Spring Data MongoRepository fornisce internamente per ottenere un oggetto per ID.

Aggiungere un nuovo utente

Aggiungeremo un nuovo utente nella funzione qui sotto.

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

Ottenere le impostazioni dell’utente

Ora che abbiamo aggiunto dei dati di esempio nel database, proviamo ad estrarne una parte.

@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.";
	}
}

Ottenere una particolare impostazione dell’utente

@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.";
	}
}

Nota nella query precedente, abbiamo ottenuto l’oggetto utente, quindi abbiamo estratto la mappa delle impostazioni complete (che poteva contenere migliaia di oggetti) e infine abbiamo ottenuto il nostro valore. Questo è un lato negativo della query di Spring Data quando la usiamo come API diretta.

Aggiungere una nuova impostazione utente

Proviamo ad aggiungere alcuni dati a un utente esistente:

@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.";
	}
}

Con tutto il codice che abbiamo scritto, è chiaro che non abbiamo dovuto scrivere nemmeno una singola riga di codice per accedere al database, a parte la definizione dell’interfaccia del repository e l’autowiring della dipendenza. Questa è la facilità che ci offre l’API Spring Data MongoRepository, ma ha anche alcuni svantaggi. Li illustreremo quando avremo definito la versione di MongoTemplate anche. Iniziamo anche con quello.

Spring Data MongoDB – MongoTemplate

Qui definiremo le query del database per MongoTemplate. Con MongoTemplate, vedrai che abbiamo un controllo molto più granulare su ciò che interrogamo e su quali dati sono inclusi nei risultati.

Definizione dell’interfaccia DAL

Per fornire un contratto al livello di accesso al database, inizieremo definendo un’interfaccia che funziona proprio come i nostri metodi incorporati di 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);
}

Implementazione dell’interfaccia DAL

Procediamo e definiamo questi metodi.

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);
		// Ora, l'oggetto utente conterrà anche l'ID
		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.";
		}
	}
}

Le implementazioni dei metodi nella classe sopra utilizzano la dipendenza di MongoTemplate. Guarda come il metodo getUserById(...) ottiene l’utente. Costruiamo una query e passiamo i parametri richiesti. Quello che ti interesserà di più è la query getUserSetting. Capiamo cosa è successo sopra:

  • Abbiamo costruito delle query con criteri per controllare l’uguaglianza.
  • Il metodo include i nomi dei campi che il risultato dovrebbe includere quando viene estratto dal DB. Ciò significa che, in questo caso, verrà estratta la chiave userSettings che risparmierà molti dati da recuperare che non sono necessari
  • Inoltre, abbiamo interrogato sia l’utente che la chiave della mappa. Se non viene trovato nessuno dei due, restituiamo dati vuoti, il che significa che la chiave richiesta non è stata trovata. Questo evita di recuperare l’oggetto Utente del tutto se la chiave richiesta non era presente

Esecuzione di test Spring Data MongoDB

Possiamo eseguire questa app semplicemente usando un singolo comando:

mvn spring-boot:run

Una volta che l’applicazione è in esecuzione, possiamo provare a salvare un nuovo utente usando questa API:

https://localhost:8102/user/create

Dato che si tratta di una richiesta POST, invieremo anche dati JSON:

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

Dato che stiamo restituendo la risposta di Mongo stessa, otterremo qualcosa del genere:

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

Puoi ottenere tutti gli utenti usando l’API come richiesta GET:

https://localhost:8102/user/

Otterremo qualcosa del genere:

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

Se si vede sopra la classe UserController, non abbiamo collegato MongoTemplate per essere utilizzato. Il frammento di codice sottostante mostra le modifiche necessarie per utilizzare MongoTemplate per leggere le impostazioni dell’utente.

//definire l'oggetto Layer di Accesso ai Dati
private final UserDAL userDAL;

//inizializzare l'oggetto DAL tramite l'autowiring del costruttore
public UserController(UserRepository userRepository, UserDAL userDAL) {
	this.userRepository = userRepository;
	this.userDAL = userDAL;
}

//cambiare l'implementazione del metodo per utilizzare DAL e quindi 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.";
    }
}

//cambiare l'implementazione del metodo per utilizzare DAL e quindi MongoTemplate
@RequestMapping(value = "/settings/{userId}/{key}", method = RequestMethod.GET)
public String getUserSetting(
        @PathVariable String userId, @PathVariable String key) {
    return userDAL.getUserSetting(userId, key);
}

Riavviare l’applicazione e eseguire gli scenari per ottenere tutte le impostazioni utente e ottenere una chiave specifica. Nell’immagine sottostante viene mostrato l’output dall’applicazione Postman.

MongoTemplate vs MongoRepository

  • MongoTemplate fornisce un controllo molto maggiore quando si tratta di interrogare i dati e di quali dati estrarre dal database.
  • Le repository di Spring Data ci forniscono una visione conveniente su come recuperare i dati.
  • MongoTemplate dipende dal database. Ciò significa che, con le repository di Spring Data, è possibile passare facilmente a un database diverso semplicemente utilizzando delle repository di Spring Data diverse per MySQL o Neo4J o qualsiasi altra cosa. Questo non è possibile con MongoTemplate.

Riepilogo Spring Boot MongoDB

Nella lezione odierna abbiamo esaminato come MongoTemplate possa fornirci maggiore controllo sui repository di Spring Data, ma può diventare un po’ complicato quando si affrontano query più complesse. Quindi, è completamente a tua discrezione decidere cosa scegliere quando sviluppi la tua idea. Sentiti libero di lasciare commenti qui sotto. Scarica il codice sorgente dal link sottostante. Assicurati di modificare le credenziali MongoDB prima di eseguire l’applicazione fornita.

Scarica il Progetto di Esempio Spring Boot MongoDB

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