Persistenza dei dati con Spring Data MongoDB

Qualche tempo fa abbiamo avuto modo di conoscere il progetto Spring Data nella sua versione dedicata a JPA.

I database relazionali sono ancora oggi molto utilizzati, basta dare un’occhiata alla sezione Databases dello Stack Overflow Developer Survey 2018 per averne conferma: tra i primi cinque risultati ci sono almeno quattro RDBMS.

Ma l’onda NoSQL continua a crescere e l’esponente di maggior rilievo rimane sempre l’ottimo MongoDB.

In questo episodio riprendiamo la nostra fantastica SuperRubricaREST! e scopriamo come sfruttare la potenza di MongoDB tramite le API di Spring Data MongoDB.

Dipendenze

Per cominciare, come di consueto, avremo bisogno di aggiungere qualche utile dipendenza al nostro pom.xml.

In questo caso ci basterà aggiungere un solo starter package:

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

et voilà, il gioco è fatto!

Repository e… documenti

Poiché MongoDB è un database basato sul concetto di documento, le nostre classi di dominio (quelle che nel caso di JPA definivamo entità) rappresenteranno, a tutti gli effetti, dei documenti.

L’implementazione del repository, come in ogni progetto basato su Spring Data, è piuttosto minimale. Ci basterà estendere l’interfaccia MongoRepository definendo nei type parameters il tipo del documento e quello utilizzato per l’ID (in questo caso, rispettivamente, Contact e String):

public interface ContactRepository extends MongoRepository<Contact, String> { }

La nostra classe Contact, invece, diventerà qualcosa di simile:

@Data
@NoArgsConstructor
@Document(collection = "contacts")
public class Contact {
    @Id
    private String id;
    private @NonNull String firstName;
    private @NonNull String lastName;
    private @NonNull String phone;
    private @NonNull String email;

}

Come vedete ho sfruttato Project Lombok per risparmiarmi un po’ di linee di codice.

Ciò che c’interessa maggiormente, però, sono due annotazioni:

  • @Id la conosciamo già: è la stessa annotazione utilizzata nella definizione delle entities JPA. La cosa interessante è che utilizzandola in accoppiata con un ID di tipo String farà sì che, in fase d’inserimento, MongoDB generi di default una chiave GUID per il documento. Ovviamente possiamo utilizzare anche altri tipi per la nostra “chiave primaria”, ma in tal caso dovremo generare e assegnare noi il valore.
  • @Document è invece un’annotazione inclusa in Spring Data MongoDB. Possiamo utilizzarla per definire esplicitamente una classe-documento, andando a specificare anche il nome della collection associata. Se invece decidiamo di ometterla, la collection avrà, per convenzione, lo stesso nome della classe.

Connessione al database

Per la nostra applicazione possiamo decidere d’installare un’istanza di MongoDB sulla nostra macchina di sviluppo oppure sfruttare uno dei tanti servizi di hosting in cloud che ci permettono di essere subito operativi (ad esempio, MongoDB Atlas e mLab prevedono anche piani gratuiti).

Indipendentemente dalla nostra scelta, nell’application.properties del progetto dovremo specificare i parametri di connessione al database, ad esempio:

spring.data.mongodb.host=localhost
spring.data.mongodb.port=27017
spring.data.mongodb.database=super-rubrica

Per effettuare dei test sulle nostre API, avremo inoltre bisogno di popolare il DB con qualche documento. Possiamo utilizzare il metodo insertMany di MongoDB, specificando una lista di oggetti:

db.contacts.insertMany([
    {
        "firstName" : "Mario",
        "lastName" : "Rossi",
        "phone" : "3332345678",
        "email" : "[email protected]",
    },
    {
        "firstName" : "Francesca",
        "lastName" : "Gialli",
        "phone" : "3332233444",
        "email" : "[email protected]",
    },
    {
        "firstName" : "Marco",
        "lastName" : "Verdi",
        "phone" : "3334545456",
        "email" : "[email protected]",
    }
]);

… oppure possiamo inserire i contatti utilizzando le REST API della nostra SuperRubricaREST!.

Piccola nota Per agevolare la navigazione e la gestione del vostro database vi consiglio di un piccolo tool: Robomongo (recentemente rinominato in Robo 3T). Ne esiste una versione gratuita con funzionalità minimali, ma che permette di espletare tutte le principali operazioni sul nostro DB.

Contacts collection

Se andiamo ad esaminare gli oggetti inseriti nella collection contacts noteremo che gli oggetti inseriti tramite il MongoRepository presentano un campo extra generato automaticamente. Il campo _class viene utilizzato dal framework per effettuare correttamente la deserializzazione degli oggetti in fase di recupero dati e permette di supportare l’ereditarietà tra classi di tipo document.

In conclusione

L’utilizzo dei database non relazionali si rivela particolarmente vantaggioso in determinati contesti applicativi nei quali i classici RDBMS mostrano qualche sintomo d’inadeguatezza.

Benché esistano moltissime declinazioni del concetto di “non relazionale” e altrettante implementazioni di ciascuna tipologia, negli ultimi anni MongoDB è diventato sinonimo di NoSQL.

In questo post abbiamo visto come il progetto Spring Data MongoDB, in accoppiata con Spring Boot, consenta di sfruttare facilmente la potenza e la flessibilità di MongoDB attraverso le ben note API del framework Spring Data.

Alla prossima,

David