Step 03 — JPA + Flyway + PostgreSQL¶
Obiettivo: persistere progetti e task in PostgreSQL con schema gestito da Flyway.
Cosa costruiamo¶
- Entità JPA
ProjecteTaskcon relazione1:N. - Repository Spring Data.
- Prima migration Flyway
V1__init.sql.
Migration¶
src/main/resources/db/migration/V1__init.sql
create table projects (
id uuid primary key,
name varchar(120) not null,
description varchar(2000),
status varchar(20) not null,
created_at timestamptz not null default now(),
updated_at timestamptz not null default now(),
version bigint not null default 0,
constraint chk_project_status check (status in ('ACTIVE', 'ARCHIVED'))
);
create table tasks (
id uuid primary key,
project_id uuid not null references projects (id) on delete cascade,
-- ...
);
Entità¶
Task.java (estratto)
@Entity
@Table(name = "tasks")
public class Task {
@Id @GeneratedValue
private UUID id;
@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "project_id", nullable = false)
private Project project;
@Enumerated(EnumType.STRING)
private TaskStatus status = TaskStatus.TODO;
@Version
private long version;
// ...
}
Concetti chiave¶
UUIDcome PK — niente sequence, niente accoppiamento a un DB. Sicuro per esporre nei path.@Enumerated(EnumType.STRING)— maiORDINAL: cambia se aggiungi enum nel mezzo.fetch = LAZYsui@ManyToOne— evita di caricare il parent quando non serve. Vedi step-05 per N+1.@Version— optimistic locking per concorrenza.ddl-auto: validate— Flyway è l'unica fonte di verità per lo schema.
application.yml rilevanti¶
spring:
datasource:
url: jdbc:postgresql://localhost:5432/sbfs
jpa:
hibernate:
ddl-auto: validate
open-in-view: false # critical!
flyway:
enabled: true
locations: classpath:db/migration
Esercizi¶
- Aggiungi un indice su
(project_id, status)nella migrationV2. - Crea una query
findTopByProject_IdOrderByDueDateAsc(UUID id)derivata. - Spiega quando
open-in-view: true(default!) è un problema.