Atividade Persistência de Dados (EstanteWeb)
Disciplina: Programação para Web 3
Assunto: Bancos de dados relacionais, MySQL e versionamento de esquema com Flyway
Professor: Prof. Me. Danilo Bueno
Grupos: duplas
Duração: 4 aulas de 50 minutos (em sala)
Importante
Antes de começar, leia o material de apoio sobre persistência de dados. É imprescindível ler antes de codar: a atividade aplica exatamente os conceitos do material. Se tiver dúvidas, releia, pergunte ao professor ou aos colegas. Você também pode consultar os slides da aula.
Contextualização
Toda vez que o servidor da EstanteWeb é reiniciado, o acervo volta a ser exatamente os mesmos livros escritos no código, e qualquer sugestão de leitura enviada por um visitante desaparece (uma consequência já observada e discutida na Semana 3). Nesta etapa, a dupla vai colocar um banco de dados de verdade no ar e preparar seu esquema com o Flyway. A aplicação, do ponto de vista de quem acessa o site, não muda nada ainda: o acervo continua vindo da lista em memória. O objetivo desta semana é só a fundação, ler e gravar dados de verdade fica para as próximas duas aulas.
O que já temos
O checkpoint de partida traz a aplicação Spring Boot das semanas anteriores, já rodando em http://localhost:8080, com:
- Todas as rotas de
PaginaController,LivroControllereSugestaoControllerfuncionando exatamente como na Semana 5, ainda sobre dados em memória (LivroRepository,SugestaoRepository). - Nenhuma dependência de banco de dados no
pom.xmlainda. - Nenhuma pasta
db/migrationainda.
Como começar
Esta semana exige um banco de dados MySQL em execução. Caso tenha instalado no laboratório pode utilizar o que já está instalado, caso contrário utilize o caminho é via Docker (mesma ferramenta já usada no fallback do httpbin, na Semana 1):
docker run --name estanteweb-mysql \
-e MYSQL_ROOT_PASSWORD=estanteweb \
-e MYSQL_DATABASE=estanteweb \
-p 3306:3306 \
-d mysql:8
Isso sobe um container MySQL 8, já com um banco chamado estanteweb criado, acessível em localhost:3306, usuário root, senha estanteweb. Se sua dupla já tiver um MySQL local instalado, pode usá-lo no lugar, criando manualmente um banco chamado estanteweb e ajustando usuário/senha na Missão 2.
Depois, como de costume:
git clonedo repositório do projeto (pule este passo se sua dupla já clonou nas semanas anteriores).git checkout semana-06-iniciopara partir exatamente do estado descrito acima.- Não rode a aplicação ainda: sem as dependências e a configuração da Missão 2, ela vai falhar ao tentar se conectar a um banco inexistente para o Spring.
Como funciona
- A atividade é feita em dupla, mas as entregas no Moodle são individuais.
- As missões são incrementais: cada uma constrói sobre a anterior, siga na ordem.
- Ao final de cada missão, teste (rodando a aplicação e, quando indicado, consultando o banco) antes de seguir.
- Responda, no caminho, às perguntas em destaque (marcadas com
>). Elas voltam no questionário do Moodle.
Cronograma
| Aula | Foco | Missões |
|---|---|---|
| 1 | O banco de dados no ar | Missão 1 |
| 2 | Conectando o Spring Boot ao banco | Missão 2 |
| 3 | A primeira migração | Missão 3 |
| 4 | Populando os dados + desafio | Missão 4 |
Missão 1: O banco de dados no ar
Objetivo: ter um MySQL em execução e confirmar acesso a ele antes de qualquer configuração no projeto Java.
1.1. Rode o comando Docker da seção “Como começar” (ou confirme seu MySQL local já está de pé). Aguarde alguns segundos: a primeira inicialização de um container MySQL demora um pouco mais que as seguintes.
1.2. Acesse o banco pela linha de comando, de dentro do próprio container:
docker exec -it estanteweb-mysql mysql -uroot -pestanteweb estanteweb
Dentro do prompt do MySQL, rode SHOW TABLES;. Deve aparecer uma lista vazia: o banco existe, mas não tem nenhuma tabela ainda.
O banco
estantewebjá existe e está vazio, mas a aplicação Java ainda não sabe que ele existe. O que falta para ligar as duas pontas?
Missão 2: Conectando o Spring Boot ao banco
Objetivo: adicionar ao projeto as dependências e a configuração necessárias para o Spring Boot se conectar ao MySQL.
2.1. No pom.xml, adicione quatro dependências: spring-boot-starter-jdbc, o driver do MySQL (com.mysql:mysql-connector-j, com <scope>runtime</scope>) e o Flyway (org.flywaydb:flyway-core e org.flywaydb:flyway-mysql). Diferente do MySQL, o Flyway não exige nenhuma instalação separada: essas duas dependências já são tudo o que ele precisa para rodar dentro da própria aplicação.
2.2. Em application.properties, adicione a configuração de conexão (spring.datasource.url, spring.datasource.username, spring.datasource.password), apontando para o banco estanteweb criado na Missão 1.
2.3. Rode a aplicação. Mesmo sem nenhuma migração ainda, observe no console uma linha do Flyway indicando que ele criou sua própria tabela de controle no banco.
O que aconteceria ao rodar a aplicação com a senha errada em
application.properties? Relembre a discussão da Semana 2 sobre por que é melhor um erro aparecer imediatamente do que a aplicação subir e falhar em silêncio.
Missão 3: A primeira migração
Objetivo: criar as tabelas do acervo e das sugestões, versionadas pelo Flyway.
3.1. Crie a pasta src/main/resources/db/migration/ e, dentro dela, o arquivo V1__criar_tabela_livro.sql, com uma tabela livro cujas colunas espelhem a classe Livro (id como chave primária autoincrementada, titulo, autor, ano, preco).
3.2. Crie V2__criar_tabela_sugestao.sql, com uma tabela sugestao cujas colunas espelhem a classe Sugestao (id, nome_cliente, livro_sugerido).
3.3. Rode a aplicação de novo e observe o console: o Flyway deve indicar as duas migrações aplicadas, em ordem. Confirme pelo terminal do MySQL (docker exec, como na Missão 1): SHOW TABLES; agora deve listar livro, sugestao e a tabela de controle do Flyway; SELECT * FROM flyway_schema_history; mostra o histórico.
O que a tabela
flyway_schema_historyguarda sobre cada migração, além do nome do arquivo? Por que isso importa quando várias pessoas do time mexem no mesmo banco?
Missão 4: Populando os dados + desafio
Objetivo: inserir, via migração, os mesmos dados que hoje só existem na lista em memória.
4.1. Crie V3__inserir_livros_iniciais.sql, com um INSERT INTO livro (...) para cada um dos livros atualmente hardcoded em LivroRepository (incluindo o título com a tag <b>, exatamente como está no código).
4.2. Rode a aplicação e confirme, pelo terminal do MySQL, que SELECT * FROM livro; retorna os mesmos livros do acervo em memória.
4.3. Note que o site (/livros, /livros/html) continua mostrando os dados da lista em memória, não os do banco: as duas fontes de dados coexistem por enquanto, sem nenhuma ligação entre si.
4.4. Desafio (opcional): depois que a Missão 4 já tiver rodado com sucesso, edite o arquivo V1__criar_tabela_livro.sql (mude qualquer detalhe, um espaço ou um tipo de coluna) e rode a aplicação de novo. Leia a mensagem de erro do Flyway com atenção. Depois, desfaça a edição.
No desafio, qual foi exatamente o problema que o Flyway apontou? Por que ele se recusa a continuar em vez de simplesmente reaplicar a migração editada?
Entrega individual
Cada integrante da dupla deve, individualmente, no Moodle:
- Responder o questionário da semana (perguntas de reflexão sobre a atividade).
- Enviar o projeto compactado em
.zip(a pasta do projeto sem a subpastatarget/, que é gerada na compilação e pesa à toa).