BLAD 03 · TEKENINGENREGISTER
DETAILBLAD 03.3 — P-03
Recipe Book
Recipes with ordered steps and ingredients. Part 2 of the series: JPA done deliberately, with the API contract written before any code.
openapi.yamlOpenAPI 3.1
generatesAPI interfaces & DTOsgenerated at build
DTOsControllersproblem+json errors
mapperRecipe aggregateJPA · Hibernate
JPAPostgreSQL 185 Flyway migrations
SPECIFICATIE
- AGGREGATE
- Recipe is the aggregate root: steps and ingredients are reached, saved and deleted only through it — cascade ALL and orphanRemoval in JPA, ON DELETE CASCADE in the schema.
- PERSISTENCE
- JPA/Hibernate through a hand-written EntityManager repository, no Spring Data. SEQUENCE ids with allocationSize 50, id-based equals, open-in-view off.
- CONCURRENCY
- @Version optimistic locking: a concurrent edit gets 409 Conflict as RFC 9457 problem details.
- QUERIES
- The list reads a RecipeSummary projection — name, description and counts — instead of loading whole aggregates.
- INTEGRITY
- CHECK constraints, case-insensitive unique names and deferrable unique step order, across 5 Flyway migrations on PostgreSQL 18.
- API
- Design-first OpenAPI 3.1: openapi-generator builds the DTOs and API interfaces from docs/api/openapi.yaml; the mappers are hand-written.
- TESTING
- 109 tests, written test-first: unit, web slice, repository and end-to-end on Testcontainers, plus ArchUnit rules that enforce the layering.
Recipeaggregate root · @Version
cascade ALL · orphanRemovalStepordered · deferrable unique
Ingredientquantity > 0 · unique name
REV. NOTE Re-ordering steps saves in one transaction thanks to deferrable unique constraints.