# crud-mysql Companion project for the article **[Spring Boot CRUD REST API with MySQL and Spring Data JPA](https://ankurm.com/spring-boot-crud-rest-api-mysql/)** on **[ankurm.com](https://ankurm.com)**. A complete Create / Read / Update / Delete API for books on **Spring Boot 4.1, Spring Data JPA (Hibernate), Flyway and MySQL 8.4**, with Bean Validation and RFC 9457 `ProblemDetail` errors. Every console block quoted in the article came out of `output/`, written by the test suite against a real MySQL server, so a claim that stops being true turns the build red. There is deliberately **no `docs/` folder**: the deeper material lives in collapsible sections inside the article itself. ## Versions | | | |---|---| | Spring Boot | 4.1.1 | | Spring Framework | 7.0.9 | | MySQL server used for `output/` | MySQL Community Server 8.4.6 (official Linux tarball, started directly; **not** Docker) | | MySQL driver | MySQL Connector/J 9.7.0 (what Boot 4.1.1 manages) | | JDK | 21 (OpenJDK 21.0.12) | | Maven | 3.9 | Only JDK 21 was used. `docker-compose.yml` was **not run** (the sandbox had no Docker). ## Quickstart ```bash docker compose up -d # or run scripts/mysql-setup.sql against a MySQL you already have mvn test # runs the scenarios and rewrites output/01-04 mvn spring-boot:run # API on http://localhost:8080/api/books ``` Defaults: `jdbc:mysql://localhost:3306/library`, user `library`, password `library`. Override with `DB_URL`, `DB_USER` and `DB_PASSWORD`. The tests start the real application and delete all rows in the `book` table first, so point them at a database you can wipe. ## Endpoints | Method and path | What it does | Success | Errors | |---|---|---|---| | `POST /api/books` | create | `201` + `Location` | `400` validation, `409` duplicate ISBN | | `GET /api/books/{id}` | read one | `200` | `404`, `400` (id not a number) | | `GET /api/books?author=&page=&size=` | list, paged, optional author filter | `200` | | | `PUT /api/books/{id}` | replace | `200` | `400`, `404`, `409` | | `DELETE /api/books/{id}` | delete | `204` | `404` | ## Source layout | Path | What it is | |---|---| | `book/Book.java` | the JPA entity, mapped to the `book` table | | `book/BookRepository.java` | a Spring Data interface: no implementation to write | | `book/BookService.java` | transactions, paging, dirty checking for the update | | `book/BookController.java` | the HTTP layer | | `book/BookRequest.java`, `BookResponse.java`, `PageResponse.java` | what crosses the wire | | `error/ApiExceptionHandler.java` | every error becomes a `ProblemDetail` | | `resources/db/migration/V1__create_book.sql` | the schema, owned by Flyway | ## Captured output | File | What it shows | |---|---| | `01-mysql-and-schema.txt` | the server and driver versions, the Hibernate dialect, the Flyway history and `SHOW CREATE TABLE` | | `02-crud-walkthrough.txt` | create, read, list (paged and filtered), update, delete: the requests are made with the JDK's `HttpClient` and printed as the equivalent curl commands, with the real responses | | `03-error-responses.txt` | validation, duplicate ISBN on create and on update, the message MySQL itself returned, 404, bad id, bad JSON | | `04-sql-per-request.txt` | the SQL Hibernate sent for each kind of request | | `05-real-curl.txt` | real `curl -i` against the packaged jar (headers included), written by `scripts/curl-demo.sh` |