API REST em Java com Spring Boot para gerenciar listas de jogos ordenáveis — o tipo de recurso em que a posição de cada item importa e precisa sobreviver a reordenações feitas pelo cliente (arrastar e soltar).
Projeto de estudo focado em praticar arquitetura de backend em camadas, mapeamento relacional com JPA e modelagem de um relacionamento N:N com atributo próprio (a posição do jogo dentro da lista) — que é onde a maioria dos exemplos introdutórios de CRUD para de ser suficiente.
Um jogo pode estar em várias listas, e uma lista tem vários jogos. Até aí é um N:N comum. A diferença é que a ordem do jogo dentro de cada lista é um dado da relação, não do jogo nem da lista.
A solução usa uma entidade de associação (Belonging) com chave primária
composta (BelongingPK, via @EmbeddedId) e um campo position. Reordenar não
é UPDATE de um campo qualquer: mover um item de uma posição para outra desloca
todos os itens entre elas — a lógica fica isolada em GameListService.move(),
anotada com @Transactional para que a lista nunca fique num estado
parcialmente reordenado.
| Método | Rota | Descrição |
|---|---|---|
GET | /games | Lista resumida de todos os jogos (GameMinDTO) |
GET | /games/{id} | Detalhe completo de um jogo (GameDTO) |
GET | /lists | Todas as listas de jogos |
GET | /lists/{listId}/games | Jogos de uma lista, na ordem definida |
POST | /lists/{listId}/replacement | Reordena: recebe sourceIndex e destinationIndex |
Exemplo de reordenação:
curl -X POST http://localhost:8080/lists/1/replacement \
-H "Content-Type: application/json" \
-d '{"sourceIndex": 3, "destinationIndex": 0}'- Camadas separadas (
controllers→services→repositories→entities): o controller não conhece JPA e a entidade nunca é serializada direto na resposta. - DTOs por caso de uso —
GameMinDTOpara listagem (só o necessário para renderizar um card) eGameDTOpara o detalhe. Evita trafegar campo demais numa tela que só precisa de título e capa. - Projection do Spring Data (
GameMinProjection) na consulta de jogos por lista: a ordenação porpositionexige uma query nativa comJOIN, e a projection mapeia o resultado sem carregar as entidades inteiras. - Perfis de configuração separados (
dev,test,prod): H2 em memória para rodar sem instalar nada, PostgreSQL em produção — mesma aplicação, semifde ambiente no código. - Seed automático via
import.sql, para o projeto subir já com dados.
Requisito: JDK 17+ (o Maven vem embutido no wrapper).
git clone https://github.com/enzozon/projeto-java.git
cd projeto-java
./mvnw spring-boot:run # Linux/macOS
mvnw.cmd spring-boot:run # WindowsA aplicação sobe em http://localhost:8080. Com o perfil de teste (H2 em
memória), o banco já sobe populado pelo import.sql e o console do H2 fica
disponível em http://localhost:8080/h2-console.
Para rodar contra PostgreSQL, ative o perfil prod e informe as variáveis de
conexão em application-prod.properties.
src/main/java/com/projeto/dslist/
├── controllers/ # GameController, GameListController — camada REST
├── services/ # regras de negócio (inclui a reordenação transacional)
├── repositories/ # Spring Data JPA + query nativa ordenada por position
├── entities/ # Game, GameList, Belonging + BelongingPK (chave composta)
├── dto/ # GameDTO, GameMinDTO, GameListDTO, ReplacementDTO
├── projections/ # GameMinProjection
└── config/ # WebConfig (CORS)
Java 17 · Spring Boot 3.5.4 · Spring Web · Spring Data JPA / Hibernate · PostgreSQL · H2 · Maven
- Testes de integração dos endpoints com
@SpringBootTeste MockMvc - Tratamento centralizado de exceções (
@ControllerAdvice) com respostas de erro padronizadas - Documentação interativa com springdoc-openapi (Swagger UI)
- Containerização com Docker Compose (API + PostgreSQL)