Sistema completo de gerenciamento de cinema desenvolvido com Spring Boot, oferecendo funcionalidades de gestão de filmes, sessões, reservas de assentos e análise de dados (analytics).
- Sobre o Projeto
- Funcionalidades
- Tecnologias Utilizadas
- Arquitetura do Sistema
- Pré-requisitos
- Instalação
- Configuração
- Executando o Projeto
- Estrutura do Banco de Dados
- Endpoints da API
- Exemplos de Uso
- Modelo de Dados
- Contribuindo
- Licença
Este é um sistema backend completo para gerenciamento de cinemas, desenvolvido como projeto educacional utilizando as melhores práticas de desenvolvimento Spring Boot. O sistema permite o gerenciamento completo de filmes, salas, sessões e reservas de assentos, além de fornecer estatísticas e análises de dados para tomada de decisões.
- API RESTful completa e bem documentada
- Arquitetura em camadas (Controller, Service, Repository)
- Persistência de dados com JPA/Hibernate
- Validações e tratamento de erros
- Transações para garantir integridade dos dados
- Analytics para análise de dados e relatórios
- CORS configurado para integração com frontend
- Listar todos os filmes cadastrados
- Filtrar filmes em cartaz
- Buscar filme por ID
- Pesquisar filmes por título
- Buscar filmes por gênero
- Listar sessões por filme e data
- Visualizar assentos disponíveis em uma sessão
- Consultar próximas sessões de um filme
- Filtrar sessões com vagas disponíveis
- Reservar assentos em sessões específicas
- Validação de disponibilidade em tempo real
- Controle de status de assentos (Disponível, Ocupado, Reservado)
- Sistema de transações para garantir consistência
- Filmes mais populares por período
- Horários mais movimentados
- Dias da semana com maior movimento
- Dashboard com resumo dos últimos 7 e 30 dias
- Java 21 - Linguagem de programação
- Spring Boot 3.5.6 - Framework principal
- Spring Data JPA - Persistência de dados
- Spring Web - API REST
- Hibernate - ORM (Object-Relational Mapping)
- Maven - Gerenciamento de dependências
- MySQL 8.0 - Sistema de gerenciamento de banco de dados
- Lombok - Redução de código boilerplate
- Jackson - Serialização/Deserialização JSON
- Spring Boot DevTools - Ferramentas de desenvolvimento
O projeto segue uma arquitetura em camadas bem definida:
cinema-backend/
│
├── src/main/java/cimema/backend/
│ ├── controller/ # Camada de Controle (REST Controllers)
│ │ ├── AnalyticsController.java
│ │ ├── FilmeController.java
│ │ └── SessaoController.java
│ │
│ ├── service/ # Camada de Serviço (Lógica de Negócio)
│ │ ├── AnalyticsService.java
│ │ ├── FilmeService.java
│ │ └── SessaoService.java
│ │
│ ├── repository/ # Camada de Persistência (Acesso a Dados)
│ │ ├── AnalyticsRepository.java
│ │ ├── AssentoRepository.java
│ │ ├── FilmeRepository.java
│ │ ├── ReservaRepository.java
│ │ ├── SalaRepository.java
│ │ └── SessaoRepository.java
│ │
│ ├── model/ # Entidades do Domínio
│ │ ├── Assento.java
│ │ ├── Filme.java
│ │ ├── Reserva.java
│ │ ├── Sala.java
│ │ ├── Sessao.java
│ │ ├── StatusAssento.java
│ │ └── StatusReserva.java
│ │
│ ├── dto/ # Data Transfer Objects
│ │ ├── FilmePopularDTO.java
│ │ └── HorarioMovimentoDTO.java
│ │
│ └── BackendApplication.java
│
├── src/main/resources/
│ └── application.properties
│
└── cinema_db.sql # Script de criação e população do banco
Recebem requisições HTTP, validam dados de entrada e retornam respostas apropriadas. Não contêm lógica de negócio.
Contêm a lógica de negócio da aplicação, orquestram operações, validam regras e coordenam múltiplos repositories.
Interface com o banco de dados. Usam Spring Data JPA para fornecer operações CRUD e queries customizadas.
Representam as entidades do domínio e suas relações. Mapeadas diretamente para tabelas do banco de dados.
Objetos otimizados para transferência de dados, especialmente para agregações e relatórios.
Antes de começar, você precisará ter instalado em sua máquina:
-
JDK 21 ou superior
- Download OpenJDK
- Verifique a instalação:
java -version
-
Maven 3.9+ (ou use o Maven Wrapper incluído)
- Download Maven
- Verifique a instalação:
mvn -version
-
MySQL 8.0+
- Download MySQL
- Verifique a instalação:
mysql --version
-
Git (para clonar o repositório)
git clone https://github.com/seu-usuario/cinema-backend.git
cd cinema-backendInicie o servidor MySQL e execute o script de criação do banco:
mysql -u root -p < cinema_db.sqlOu manualmente:
-- Conecte ao MySQL
mysql -u root -p
-- Execute os comandos do arquivo cinema_db.sql
source /caminho/para/cinema_db.sqlO script irá:
- Criar o banco de dados
cinema_db - Criar todas as tabelas necessárias
- Popular com dados de exemplo (filmes, salas, sessões)
- Gerar automaticamente os assentos para cada sessão
Edite o arquivo src/main/resources/application.properties:
# Database Configuration
spring.datasource.url=jdbc:mysql://localhost:3306/cinema_db
spring.datasource.username=root
spring.datasource.password=SUA_SENHA_AQUI
# JPA Configuration
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect
# Server Configuration
server.port=8080SUA_SENHA_AQUI pela senha do seu usuário MySQL.
server.port=8081spring.jpa.show-sql=falseEdite as anotações @CrossOrigin nos controllers:
@CrossOrigin(origins = {"http://seu-dominio.com", "http://localhost:3000"})Linux/Mac:
./mvnw spring-boot:runWindows:
mvnw.cmd spring-boot:runmvn spring-boot:run# Compilar o projeto
mvn clean package
# Executar o JAR gerado
java -jar target/backend-0.0.1-SNAPSHOT.jarApós iniciar, você verá no console algo como:
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v3.5.6)
...
Started BackendApplication in 3.456 seconds
Acesse: http://localhost:8080/api/filmes
┌─────────────┐ ┌──────────────┐ ┌─────────────┐
│ FILMES │ │ SESSOES │ │ SALAS │
├─────────────┤ ├──────────────┤ ├─────────────┤
│ id (PK) │───┐ │ id (PK) │ ┌───│ id (PK) │
│ titulo │ │ │ filme_id (FK)│────┘ │ nome │
│ duracao │ │ │ sala_id (FK) │ │ capacidade │
│ genero │ └────→│ data_sessao │ │ tipo │
│ ... │ │ horario │ │ ativa │
└─────────────┘ │ preco │ └─────────────┘
│ ... │
└──────┬───────┘
│
┌──────────┴───────────┐
↓ ↓
┌───────────────┐ ┌──────────────┐
│ ASSENTOS │ │ RESERVAS │
├───────────────┤ ├──────────────┤
│ id (PK) │←────┐│ id (PK) │
│ sessao_id(FK) │ └│ sessao_id(FK)│
│ numero_assento│ │ assento_id(FK)│
│ status │ │ cpf_cliente │
└───────────────┘ │ data_reserva │
│ status │
└──────────────┘
Armazena informações dos filmes disponíveis no cinema.
Representa as salas físicas do cinema com suas capacidades e tipos.
Eventos específicos de exibição (filme + sala + data/hora + preço).
Assentos individuais de cada sessão com seus status.
Registro das reservas feitas pelos clientes.
http://localhost:8080/api
GET /filmesResposta:
[
{
"id": "duna-2",
"titulo": "Duna: Parte Dois",
"duracao": "2h 46min",
"genero": "Ficção Científica, Aventura",
"classificacao": "14 anos",
"descricao": "Paul Atreides se une a Chani...",
"posterUrl": "../images/dunapt2-capa.webp",
"emCartaz": true
}
]GET /filmes/em-cartazGET /filmes/{id}Exemplo:
GET /filmes/duna-2GET /filmes/buscar?titulo={titulo}Exemplo:
GET /filmes/buscar?titulo=DunaGET /sessoes/filme/{filmeId}?data={data}Exemplo:
GET /sessoes/filme/duna-2?data=2025-12-10Resposta:
[
{
"id": 1,
"sala": {
"id": 1,
"nome": "Sala 1",
"tipo": "2D"
},
"dataSessao": "2025-12-10",
"horario": "14:00:00",
"tipoExibicao": "2D DUBLADO",
"preco": 25.00,
"assentosDisponiveis": 100
}
]GET /sessoes/{id}/assentosExemplo:
GET /sessoes/1/assentosResposta:
{
"sessao": {
"id": 1,
"dataSessao": "2025-12-10",
"horario": "14:00:00"
},
"assentos": [
{
"id": 1,
"numeroAssento": "A1",
"status": "DISPONIVEL"
},
{
"id": 2,
"numeroAssento": "A2",
"status": "OCUPADO"
}
],
"assentosDisponiveis": 98
}POST /sessoes/{sessaoId}/reservar?numeroAssento={numero}&cpf={cpf}Exemplo:
POST /sessoes/1/reservar?numeroAssento=A5&cpf=12345678900Resposta de Sucesso:
{
"mensagem": "Reserva realizada com sucesso!",
"reserva": {
"id": 1,
"cpfCliente": "12345678900",
"dataReserva": "2025-12-05T10:30:00",
"status": "CONFIRMADA"
}
}Resposta de Erro:
"Assento já está ocupado ou reservado"GET /analytics/filmes-populares?inicio={data}&fim={data}Exemplo:
GET /analytics/filmes-populares?inicio=2025-12-01&fim=2025-12-31Resposta:
{
"periodo": "2025-12-01 a 2025-12-31",
"totalFilmes": 5,
"filmes": [
{
"titulo": "Duna: Parte Dois",
"filmeId": "duna-2",
"totalVendas": 150,
"receitaTotal": 3750.00
}
]
}GET /analytics/horarios-movimento?inicio={data}&fim={data}GET /analytics/dashboardResposta:
{
"filmesPopularesSemana": [...],
"horariosPopularesMes": [...],
"resumoPeriodo": {
"semana": "2025-11-28 a 2025-12-05",
"mes": "2025-11-05 a 2025-12-05"
}
}// 1. Buscar filmes em cartaz
fetch('http://localhost:8080/api/filmes/em-cartaz')
.then(response => response.json())
.then(filmes => console.log(filmes));
// 2. Buscar sessões do filme escolhido
fetch('http://localhost:8080/api/sessoes/filme/duna-2?data=2025-12-10')
.then(response => response.json())
.then(sessoes => console.log(sessoes));
// 3. Ver assentos disponíveis
fetch('http://localhost:8080/api/sessoes/1/assentos')
.then(response => response.json())
.then(dados => console.log(dados));
// 4. Reservar assento
fetch('http://localhost:8080/api/sessoes/1/reservar?numeroAssento=A5&cpf=12345678900', {
method: 'POST'
})
.then(response => response.json())
.then(resultado => console.log(resultado));// Buscar filmes mais vendidos do mês
const dataInicio = '2025-12-01';
const dataFim = '2025-12-31';
fetch(`http://localhost:8080/api/analytics/filmes-populares?inicio=${dataInicio}&fim=${dataFim}`)
.then(response => response.json())
.then(relatorio => {
console.log('Filmes mais vendidos:', relatorio.filmes);
console.log('Receita total do período:',
relatorio.filmes.reduce((acc, f) => acc + f.receitaTotal, 0)
);
});Um filme pode ter várias sessões, mas cada sessão pertence a um único filme.
Uma sala pode ter várias sessões, mas cada sessão acontece em uma única sala.
Uma sessão tem vários assentos, cada assento pertence a uma sessão específica.
Uma sessão pode ter várias reservas.
Um assento pode ter várias reservas ao longo do tempo (histórico).
DISPONIVEL- Assento livre para reservaOCUPADO- Assento vendido/confirmadoRESERVADO- Assento temporariamente reservado
CONFIRMADA- Reserva confirmadaCANCELADA- Reserva canceladaFINALIZADA- Cliente compareceu
# Listar filmes
curl http://localhost:8080/api/filmes
# Buscar sessões
curl "http://localhost:8080/api/sessoes/filme/duna-2?data=2025-12-10"
# Reservar assento
curl -X POST "http://localhost:8080/api/sessoes/1/reservar?numeroAssento=A5&cpf=12345678900"- Importe a coleção de endpoints (se disponível)
- Configure a base URL:
http://localhost:8080/api - Teste cada endpoint conforme documentado
Solução: Verifique as credenciais no application.properties
Solução: Execute o script cinema_db.sql novamente
Solução: Altere a porta no application.properties ou finalize o processo que está usando a porta 8080
Solução: Verifique se o MySQL está rodando: sudo service mysql status
Contribuições são bem-vindas! Para contribuir:
- Faça um Fork do projeto
- Crie uma branch para sua feature (
git checkout -b feature/NovaFuncionalidade) - Commit suas mudanças (
git commit -m 'Adiciona nova funcionalidade') - Push para a branch (
git push origin feature/NovaFuncionalidade) - Abra um Pull Request
Este projeto está sob a licença MIT. Veja o arquivo LICENSE para mais detalhes.
Desenvolvido como projeto educacional para aprendizado de Spring Boot e desenvolvimento de APIs RESTful.
⭐ Se este projeto foi útil para você, considere dar uma estrela no repositório!
📧 Dúvidas ou sugestões? Abra uma issue!