This project demonstrates a simple Java REST API built with Spring Boot, Spring Data JPA, and PostgreSQL, running the database in Docker.
Based on the course:
Spring Boot Tutorial for Beginners | Full Course 2025 by amigoscode
- Java 21
- Spring Boot
- Spring Data JPA (Hibernate)
- PostgreSQL
- Docker & Docker Compose
services:
db:
container_name: postgres-spring-boot
image: postgres:18.1-alpine
restart: unless-stopped
environment:
POSTGRES_USER: postgres # database name will be the same as username
POSTGRES_PASSWORD:
PGDATA: /data/postgres
volumes:
- db:/data/postgres
ports:
- "5332:5432"
networks:
- db
networks:
db:
driver: bridge
volumes:
db:docker compose up -d- register - > server
- Host name: localhost
- Port: 5332
- Connect
docker exec -it (container id) bashpsql -U (username = postgres)\l \list -- list databases
CREATE DATABASE spring;
\c spring \connect -- connect to database
\q -- exit psql
\c postgres -- exit to base database
\d -- list tables
\d engineers -- show table structureDELETE DATABASE name;
docker compose down -v
-v - removes data volumes and your db (is needed to create db again with docker compose up)SELECT * FROM engineers;Example output:
id | name
----+--------
1 | Albert
2 | Megan
@Query("SELECT DISTINCT e FROM SoftwareEngineer e LEFT JOIN FETCH e.techStack")
List<SoftwareEngineer> findAllWithTechStack();FETCH→ forces eager loading of related collectionsLEFT JOIN→ includes engineers without tech stackDISTINCT→ removes duplicate entity instances caused by joins
- Fetches SoftwareEngineer entities
- Loads
@ElementCollection techStackeagerly - Prevents duplicate entities using
DISTINCT
SELECT e.id, e.name, t.tech_stack
FROM software_engineer e
LEFT JOIN software_engineer_tech_stack t
ON e.id = t.software_engineer_id;- Used for REST APIs
- Returns JSON / XML responses
- Combines
@Controller+@ResponseBody
- Used for MVC applications
- Returns HTML views (Thymeleaf, JSP, etc.)
- JPA entities must have a no-args constructor
@NoArgsConstructor-
Avoid implementing
equals()andhashCode()when using generated IDs- Unless explicitly designed to ignore the ID
- Incorrect implementations can break Hibernate behavior
- Docker simplifies PostgreSQL setup
- JPQL operates on entities, not tables
JOIN FETCHis essential for loading@ElementCollection- Never expose entities directly in APIs — use DTOs