Programação para Web 3

Persistência de Dados

Prof. Me. Danilo Bueno

Agenda

  1. Por que persistir dados
  2. Bancos de dados relacionais e SGBDs
  3. Persistindo o cardápio, passo a passo

Por que persistir dados

Dados que não sobrevivem

  • Uma List Java existe apenas dentro da memória do processo
  • Ao encerrar o processo, a memória é liberada e os dados desaparecem

Um reinício de servidor, uma queda de energia ou um redeploy têm o mesmo efeito.

Um processo separado

[ Aplicação Spring Boot ]  ──── conexão de rede ────▶  [ Banco de dados ]
   dados somem ao reiniciar                             dados sobrevivem

O banco de dados roda como um processo independente, com armazenamento próprio em disco.

Bancos de dados relacionais e SGBDs

Tabelas e chave primária

tabela: produto
┌────┬──────────────┬────────┐
│ id │ nome         │ preco  │
├────┼──────────────┼────────┤
│ 1  │ Espresso     │ 6.00   │
│ 2  │ Cappuccino   │ 9.00   │
└────┴──────────────┴────────┘
  • Colunas e linhas: os tipos de dado e os registros da tabela
  • Chave primária (id): identifica cada linha de forma única, geralmente numérica e autoincrementada

É por meio da chave primária que outras partes do sistema se referem a um registro específico, sem ambiguidade.

O que é um SGBD

  • Programa que armazena tabelas e garante a integridade dos dados
  • Responde a consultas escritas em SQL, a linguagem padrão de bancos relacionais
  • Nesta disciplina usamos o MySQL: gratuito, amplamente usado, com boa integração com o ecossistema Java

Persistindo o cardápio, passo a passo

Subindo o banco com Docker

docker run --name cafeteria-mysql \  -e MYSQL_ROOT_PASSWORD=cafeteria \  -e MYSQL_DATABASE=cafeteria \  -p 3306:3306 \  -d mysql:8

O MySQL roda como um processo separado da aplicação Java; por isso precisa do Docker.

Testando o acesso

docker exec -it cafeteria-mysql mysql -uroot -pcafeteria cafeteria
SHOW TABLES;-- Empty set

O banco existe; a aplicação Java ainda não sabe disso.

As dependências: banco de dados

<dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-jdbc</artifactId></dependency><dependency>    <groupId>com.mysql</groupId>    <artifactId>mysql-connector-j</artifactId>    <scope>runtime</scope></dependency>

O starter-jdbc traz a classe JdbcTemplate, usada apenas a partir da próxima aula.

A URL de conexão

jdbc:mysql://localhost:3306/cafeteria
             └───┬───┘ └┬─┘ └───┬───┘
                host   porta   banco

A mesma anatomia de URL estudada na primeira semana: host, porta e caminho.

A configuração no projeto

spring.datasource.url=jdbc:mysql://localhost:3306/cafeteriaspring.datasource.username=rootspring.datasource.password=cafeteria

application.properties guarda a senha em texto puro: aceitável só em ambiente de estudo.

Um banco conectado, mas vazio

  • A aplicação já sabe onde está o banco e como se autenticar
  • Nenhuma tabela existe ainda: criar o esquema é o próximo problema

Um mesmo esquema precisa ser recriado, na mesma ordem, em cada ambiente: o do desenvolvedor, o de testes, o de produção.

É isso que o Flyway resolve

  • Aplica ao esquema do banco a mesma lógica que o Git aplica ao código
  • Cada mudança de esquema vira um arquivo de migração, versionado junto do projeto

Sem essa disciplina, é fácil um ambiente ficar com uma estrutura diferente dos demais.

O que é o Flyway

  • Ferramenta de migração de banco de dados: aplica scripts SQL versionados, em ordem, e registra o que já foi executado
  • Roda embutida na própria aplicação, na inicialização — não é um processo externo, como o MySQL

Garante que todo ambiente (desenvolvimento, testes, produção) passe exatamente pelas mesmas migrações, na mesma ordem, e chegue ao mesmo esquema.

A dependência do Flyway

<dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-flyway</artifactId></dependency><dependency>    <groupId>org.flywaydb</groupId>    <artifactId>flyway-mysql</artifactId></dependency>

Assim como o driver do MySQL, o Flyway é só mais uma biblioteca: nenhum processo, nenhuma instalação separada. O starter do Spring Boot já configura o Flyway automaticamente com o DataSource da aplicação.

O Flyway em ação

Creating Schema History table `cafeteria`.`flyway_schema_history` ...
Successfully applied 0 migrations to schema `cafeteria`
  • Mesmo sem nenhuma migração, ele já cria sua própria tabela de controle
  • É a dependência do slide anterior rodando pela primeira vez, dentro da própria aplicação

Migrações numeradas

db/migration/
├── V1__criar_tabela_produto.sql
└── V2__criar_tabela_pedido.sql

O Flyway localiza esses arquivos pela convenção de nome, sem nenhuma configuração adicional.

Anatomia do nome do arquivo

V1__criar_tabela_produto.sql
└┬┘ └──────────┬───────────┘
 │             descrição
versão
  • V — prefixo fixo: migração versionada
  • Número — define a ordem em que o Flyway aplica os scripts
  • __ (dois underscores) — separa a versão da descrição
  • Descrição — texto livre, mas legível: é o que fica registrado no histórico

O Flyway ordena e identifica cada migração só pelo nome do arquivo: renomear uma migração já aplicada altera seu checksum e quebra a conferência.

Primeira migração: produtos

-- V1__criar_tabela_produto.sqlCREATE TABLE produto (    id BIGINT AUTO_INCREMENT PRIMARY KEY,    nome VARCHAR(255) NOT NULL,    preco DECIMAL(10,2) NOT NULL);

A coluna id, autoincrementada, é a chave primária: identifica cada linha sem ambiguidade.

Segunda migração: pedidos

-- V2__criar_tabela_pedido.sqlCREATE TABLE pedido (    id BIGINT AUTO_INCREMENT PRIMARY KEY,    nome_cliente VARCHAR(255) NOT NULL,    quantidade INT NOT NULL);

As duas migrações são aplicadas em ordem, na próxima vez que a aplicação subir.

Confirmando no MySQL

SHOW TABLES;-- produto, pedido, flyway_schema_historySELECT * FROM flyway_schema_history;-- V1 e V2, cada uma com seu checksum

A aplicação e o banco agora existem lado a lado, ainda sem nenhuma ligação entre eles.

Checksum: não edite o que já rodou

  • flyway_schema_history guarda um código de verificação de cada arquivo aplicado
  • Editar uma migração já aplicada muda esse código

O Flyway recusa continuar se o checksum calculado não bater com o registrado: qualquer ajuste vira uma migração nova.

Obrigado!

Prof. Me. Danilo Bueno
[email protected]