Esercitazioni di Spring Boot 4: lavorare con i database

In questa nuova esercitazione vedremo come collegare il nostro servizio REST ad un database MySQL in cui verranno memorizzati i dati relativi ai calciatori.

Per fare questo ci serviremo del progetto Spring Data che fornisce tutti gli strumenti necessari per gestire la persistenza. In particolare offre delle interfacce che consentono l’accesso ai dati, indipendentemente dal DBMS utilizzato. In questo modo potremo passare da una soluzione ad un’altra senza dover riscrivere il nostro codice.

Mettiamoci subito all’opera.

In primo luogo sono richieste due ulteriori dipendenze per gestire JPA (Java Persistence API)

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

e MySQL (attraverso un opportuno connector)

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
 </dependency>

Diamo per scontato che sia disponibile un’istanza di MySQL in esecuzione localmente (come in questo esempio) o su un server remoto.

Nel file application.properties aggiungiamo i parametri di configurazione del database utilizzato

spring.jpa.hibernate.ddl-auto=create
spring.datasource.url=jdbc:mysql://localhost:3306/players
spring.datasource.username=root
spring.datasource.password=root

Si tratta della stringa di connessione al database in cui sono riportati l’host (localhost), la porta (3306 quella di default), il nome del database (players) e le relative credenziali di accesso.

Particolare attenzione va riservata alla proprietà specificata nella prima riga, che consente di creare in automatico lo schema della tabella. Tale operazione sarà effettuata ad ogni riavvio. Il suo utilizzo “in produzione” è caldamente sconsigliato perché, lavorando con un database esistente, si andrebbero a cancellare i dati già presenti.

E’ possibile che venga riportato il seguente errore

Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.

per cui disabilitiamo temporaneamente SSL (Secure Socket Layer) modificando la stringa di connessione nel modo seguente

spring.datasource.url=jdbc:mysql://localhost:3306/players?useSSL=false

Ora dobbiamo creare un’entità, ovvero una classe opportunamente annotata, che sarà il fulcro del mapping tra gli oggetti Java e il database. In particolare ciascuna istanza di questa classe conterrà i dati da salvare nel database oppure quelli recuperati da quest’ultimo in fase di lettura.

In sostanza si tratta del classico POJO (nel nostro caso la classe Player) a cui sono state aggiunte delle annotazioni specifiche che andiamo a commentare.

@Entity indica per l’appunto che la classe rappresenta un’entità e come tale verrà trattata da Spring, mentre @id identifica l’attributo che fungerà da chiave primaria per il database. In particolare abbiamo scelto la generazione automatica dei valori. Volendo sarebbe possibile assegnare direttamente un valore all’id ma occorrerebbe gestire i vincoli imposti dalla primary key. Se non strettamente necessario meglio lasciar fare al framework.

Per una migliore organizzazione del codice la classe Player è stata inserita nella cartella models che ospiterà tutte le entità dell’applicazione.

Ma come si riesce ad interagire con il database per l’inserimento e/o il recupero dei dati?

Introduciamo il concetto di repository, che consente a Spring Data di fare la “magia”.

A noi spetta il compito di creare un’interfaccia, che chiameremo PlayersRepository e posizioneremo nella cartella repositories.

Tale interfaccia va annotata con @Repository, che non è altro che una specializzazione di @Component e serve ad affidare a Spring la gestione del lifecycle.

Tale interfaccia deve estendere la JpaRepository indicando il tipo dell’entità e quello della chiave primaria. Sarebbe possibile estendere anche la CrudRepository che però non gestisce altrettanto bene la paginazione dei risultati.

In sostanza si tratta di scrivere il seguente codice


@Repository
public interface PlayerRepository extends JpaRepository<Player, Long> {
}

Non è richiesta alcuna implementazione in quanto Spring si occuperà di metterci a disposizione una serie di metodi pronti all’uso come

  • findAll()
  • findOne()
  • save()
  • delete()

per citarne alcuni. Quindi il nostro “sforzo” di programmazione è davvero ridotto all’osso.

In realtà abbiamo a disposizione strumenti ben più complessi, come i query method, che per ora tralasciamo per semplificare al massimo il tutorial.

Non ci resta che collegare il repository con il controller REST, attraverso un service.

Nella precedente esercitazione abbiamo parlato dell’importanza di un service per separare gli endpoint presenti nel controller dai metodi che gestiscono effettivamente le richieste.

Nel nostro caso si tratterà di PlayerServiceDB. Sempre nell’ottica di una migliore organizzazione del codice è stata introdotta l’interfaccia PlayerService. In questo modo sarà ridotto al minimo l’impatto delle modifiche sul controller.

Infatti non dovremo fare altro che “iniettare” il nuovo service con
@Autowired
private PlayerServiceDB playerService;

sostituendo il precedente. Non è richiesta alcun’altra modifica dal momento che tutti i service implementano la stessa interfaccia.

Ovviamente, sotto il cofano,  il PlayerServiceDB utilizzerà i metodi del repository JPA che abbiamo creato e che sarà “iniettato” al suo interno.

Dopo aver compilato ed eseguito l’applicazione, proviamo ad inserire un nuovo giocatore da riga di comando

curl -X POST -H "Content-Type: application/json" -d '{"firstName":"Gonzalo","lastName":"Higuain","team":"Napoli","position":"forward"}' http://localhost:8081/players-0.0.1-SNAPSHOT/players

Come possiamo notare dai log l’inserimento è avvenuto con successo

inserimento-calciatore

Aggiornando la lista dei calciatori vedremo un nuovo elemento a cui è stata assegnata automaticamente la primary key che non avevamo specificato nel json.

lista-aggiornata

Discorso analogo per le altre operazioni che potrete testare direttamente.

La prossima volta vedremo come documentare le API servendoci di Swagger.

ESERCITAZIONI DI SPRING BOOT

 

Lascia una risposta

L'indirizzo email non verrà pubblicato. I campi obbligatori sono contrassegnati *

Utilizzando il sito, accetti l'invio dei cookies da parte nostra. Maggiori informazioni

Questo sito utilizza i cookies per fornire la migliore esperienza di navigazione possibile. Continuando ad utilizzarlo senza modificare le impostazioni o cliccando su "Accetta" acconsenti al loro utilizzo.

Chiudi