Introduzione
Nell’articolo precedente, abbiamo introdotto le basi di Spring Boot, creato un progetto base e sviluppato una semplice API. In questa seconda parte, collegheremo il progetto a un database, utilizzando PostgreSQL per la persistenza e la gestione dei dati.
PostgreSQL
PostgreSQL, nato nel 1985 come “post-ingres” grazie a Michael Stonebraker, è un’alternativa potente a database relazionali come MySQL. Una sua caratteristica unica è la possibilità di definire nuovi tipi di dati e utilizzare l’ereditarietà tra tipi. Maggiori dettagli sono disponibili sul sito ufficiale di PostgreSQL.
Configurazione di PostgreSQL in Spring Boot
Installazione del Database
Prima di proseguire, è necessario installare PostgreSQL. Questa guida offre istruzioni dettagliate per l’installazione.
Aggiungere le Dipendenze
Aggiungiamo al file pom.xml le dipendenze necessarie:
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
Queste dipendenze forniscono gli strumenti per interagire con il database e gestire le entità. Non è necessario indicare la versione del driver PostgreSQL: se ne occupa Spring Boot, scegliendone una compatibile. Se usi IntelliJ, ricorda di aggiornare il progetto per applicare le modifiche al pom.xml.
Configurare i Parametri di Connessione
Nel file application.properties, configuriamo i parametri per collegare Spring Boot a PostgreSQL:
spring.datasource.url=jdbc:postgresql://localhost:5432/NOME_DB
spring.datasource.username=USERNAME
spring.datasource.password=PASSWORD
Non serve specificare il driver: Spring Boot lo ricava automaticamente dall’URL di connessione. Aggiungiamo anche:
spring.jpa.hibernate.ddl-auto=update
per permettere a Spring Boot di generare automaticamente lo schema delle entità di dominio.
Creazione delle Entità di Dominio
Creiamo un’entità di dominio rappresentante un utente.
In un nuovo package chiamato domain, creiamo il file User.java:
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
public User() {}
public User(String username) {
this.username = username;
}
// Getter e Setter
}
- @Entity definisce questa classe come entità.
- @Table indica il nome della tabella sul database. Il nome “users” è specificato perché “user” è una parola riservata in PostgreSQL.
- @Id identifica la chiave primaria.
- @GeneratedValue permette a PostgreSQL di generare automaticamente un ID univoco.
Repository
I repository offrono i metodi necessari per le operazioni CRUD. Creiamo un’interfaccia UserRepository.java in un nuovo package chiamato repository:
@Repository
public interface UserRepository extends JpaRepository<User, Long> {}
L’interfaccia estende JpaRepository, ereditando metodi per le operazioni CRUD.
DTO
Per creare o modificare un utente, il client invierà i dati nel body della richiesta in formato JSON, ad esempio {"username": "user1"}. Per permettere a Spring di convertire automaticamente quel JSON in un oggetto Java, definiamo una classe che ne descrive la struttura: un DTO (Data Transfer Object).
In un nuovo package chiamato dto, creiamo il file UserRequest.java:
public class UserRequest {
private String username;
public UserRequest() {}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}
Il nome dell’attributo deve corrispondere a quello del campo nel JSON. Senza un DTO, dichiarando il parametro semplicemente come String, Spring ci consegnerebbe l’intero body così com’è, graffe e virgolette comprese.
Controller
Creiamo ora il controller per gestire le operazioni sugli utenti. In UserController.java scriviamo:
@RestController
@RequestMapping("/user")
public class UserController {
private final UserRepository userRepository;
public UserController(UserRepository userRepository) {
this.userRepository = userRepository;
}
}
Definire le CRUD
Aggiungiamo i metodi per le CRUD:
@PostMapping(value = "/register")
public ResponseEntity<User> register(@RequestBody UserRequest request) {
User newUser = new User(request.getUsername());
userRepository.save(newUser);
return ResponseEntity.ok(newUser);
}
@GetMapping(value = "")
public ResponseEntity<List<User>> getAll() {
return ResponseEntity.ok(userRepository.findAll());
}
@GetMapping(value = "/{userId}")
public ResponseEntity<User> getById(@PathVariable Long userId) {
return userRepository.findById(userId)
.map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build());
}
@PutMapping(value = "/{userId}")
public ResponseEntity<User> updateById(@PathVariable Long userId, @RequestBody UserRequest request) {
return userRepository.findById(userId).map(user -> {
user.setUsername(request.getUsername());
userRepository.save(user);
return ResponseEntity.ok(user);
}).orElse(ResponseEntity.notFound().build());
}
@DeleteMapping(value = "/{userId}")
public ResponseEntity<Void> deleteById(@PathVariable Long userId) {
return userRepository.findById(userId).map(user -> {
userRepository.delete(user);
return ResponseEntity.ok().build();
}).orElse(ResponseEntity.notFound().build());
}
Questi metodi consentono di registrare nuovi utenti, recuperare utenti per ID o tutti gli utenti, aggiornare e cancellare utenti. Nei metodi di registrazione e modifica, l’annotazione @RequestBody applicata a un parametro di tipo UserRequest indica a Spring di convertire il JSON ricevuto nel nostro DTO.
Test delle API
1. Recupero della Lista Utenti
- Metodo: GET
- URL: localhost:8080/user
- Risposta:
[]se il DB è vuoto.
2. Creazione Nuovo Utente
- Metodo: POST
- URL: localhost:8080/user/register
- Body:
{"username": "user1"} - Risposta:
{"id": 1, "username": "user1"}
3. Recupero Utente per ID
- Metodo: GET
- URL: localhost:8080/user/1
- Risposta:
{"id": 1, "username": "user1"}se l’ID esiste, altrimenti 404 Not Found.
4. Modifica Utente
- Metodo: PUT
- URL: localhost:8080/user/1
- Body:
{"username": "user2"} - Risposta:
{"id": 1, "username": "user2"}
5. Cancellazione Utente
- Metodo: DELETE
- URL: localhost:8080/user/1
- Risposta: 200 OK
Conclusione
In questa seconda parte, abbiamo esplorato come collegare un’applicazione Spring Boot a PostgreSQL e persistere i dati. Nella prossima parte, esamineremo come implementare un sistema di autenticazione con JWT Token e Spring Security.
Il codice completo di questo esempio è disponibile a questo link.