🗄️ Spring Boot & Conexão com Banco de Dados
Domine a configuração e integração de bancos de dados em aplicações Spring Boot
1. Introdução ao Spring Boot e Bancos de Dados
Spring Boot é um framework que simplifica a criação de aplicações Spring auto-contidas e prontas para produção. Quando você precisa conectar sua aplicação a um banco de dados, o Spring Boot oferece várias estratégias e configurações.
A configuração do banco de dados em Spring Boot é feita através de arquivos de propriedades. Os dois formatos mais comuns são: application.properties (formato chave=valor) e application.yml (formato YAML hierárquico).
Neste guia, você aprenderá a configurar conexões com MySQL, PostgreSQL e H2, usando ambos os formatos de configuração.
2. 🔧 Configuração com application.properties
O arquivo application.properties usa o formato tradicional de propriedades Java (chave=valor).
📍 Localização do Arquivo
Caminho padrão: src/main/resources/application.properties
Configuração MySQL
# ========== MySQL Configuration ==========
spring.datasource.url=jdbc:mysql://localhost:3306/nome_banco
spring.datasource.username=root
spring.datasource.password=sua_senha
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# ========== JPA/Hibernate Configuration ==========
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect
spring.jpa.properties.hibernate.format_sql=true
# ========== Connection Pool ==========
spring.datasource.hikari.maximum-pool-size=10
spring.datasource.hikari.minimum-idle=5
spring.datasource.hikari.connection-timeout=20000
📌 Explicação das Propriedades:
- spring.datasource.url: URL de conexão com o banco (host:porta/nome_banco)
- spring.datasource.username: Usuário para autenticação
- spring.datasource.password: Senha para autenticação
- spring.datasource.driver-class-name: Driver JDBC específico
- spring.jpa.hibernate.ddl-auto: Estratégia para criar/atualizar tabelas
- spring.jpa.show-sql: Exibe SQL gerado no console
- spring.jpa.properties.hibernate.dialect: Dialeto SQL específico do banco
Configuração PostgreSQL
# ========== PostgreSQL Configuration ==========
spring.datasource.url=jdbc:postgresql://localhost:5432/nome_banco
spring.datasource.username=postgres
spring.datasource.password=sua_senha
spring.datasource.driver-class-name=org.postgresql.Driver
# ========== JPA/Hibernate ==========
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQL10Dialect
spring.jpa.properties.hibernate.format_sql=true
Configuração H2 (Banco em Memória - Desenvolvimento)
# ========== H2 Configuration (In-Memory) ==========
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
# ========== H2 Console (Optional) ==========
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console
# ========== JPA/Hibernate ==========
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.show-sql=true
✓ Propriedades ddl-auto:
- create: Cria tabelas a cada execução (deleta dados antigos)
- create-drop: Cria e deleta ao encerrar (ideal para testes)
- update: Atualiza schema sem perder dados (produção)
- validate: Valida sem fazer mudanças
- none: Sem ação automática
3. 📋 Configuração com application.yml
O arquivo application.yml usa o formato YAML, que é mais legível e hierárquico.
📍 Localização do Arquivo
Caminho padrão: src/main/resources/application.yml
Configuração MySQL em YAML
# ========== MySQL Configuration ==========
spring:
datasource:
url: jdbc:mysql://localhost:3306/nome_banco
username: root
password: sua_senha
driver-class-name: com.mysql.cj.jdbc.Driver
# ========== JPA/Hibernate Configuration ==========
jpa:
hibernate:
ddl-auto: update
show-sql: true
properties:
hibernate:
dialect: org.hibernate.dialect.MySQL8Dialect
format_sql: true
# ========== Connection Pool ==========
datasource:
hikari:
maximum-pool-size: 10
minimum-idle: 5
connection-timeout: 20000
Configuração PostgreSQL em YAML
# ========== PostgreSQL Configuration ==========
spring:
datasource:
url: jdbc:postgresql://localhost:5432/nome_banco
username: postgres
password: sua_senha
driver-class-name: org.postgresql.Driver
jpa:
hibernate:
ddl-auto: update
show-sql: true
properties:
hibernate:
dialect: org.hibernate.dialect.PostgreSQL10Dialect
format_sql: true
jdbc:
batch_size: 20
fetch_size: 50
Configuração H2 em YAML
# ========== H2 Configuration ==========
spring:
datasource:
url: jdbc:h2:mem:testdb
driverClassName: org.h2.Driver
username: sa
password:
h2:
console:
enabled: true
path: /h2-console
jpa:
database-platform: org.hibernate.dialect.H2Dialect
hibernate:
ddl-auto: create-drop
show-sql: true
properties:
hibernate:
format_sql: true
🎨 Vantagens do YAML:
- Mais legível e organizado hierarquicamente
- Reduz repetição de prefixos
- Melhor para configurações complexas
- Suporta listas e estruturas aninhadas
4. 🌍 Configuração para Múltiplos Ambientes
É comum ter diferentes configurações para desenvolvimento, testes e produção. Spring Boot suporta múltiplos arquivos de configuração.
Estrutura de Arquivos
src/main/resources/
├── application.yml # Configuração padrão
├── application-dev.yml # Desenvolvimento
├── application-test.yml # Testes
└── application-prod.yml # Produção
application-dev.yml (Desenvolvimento)
# ========== Development Environment ==========
spring:
datasource:
url: jdbc:mysql://localhost:3306/dev_db
username: root
password: root123
jpa:
hibernate:
ddl-auto: update
show-sql: true
properties:
hibernate:
format_sql: true
use_sql_comments: true
server:
port: 8080
error:
include-stacktrace: always
application-prod.yml (Produção)
# ========== Production Environment ==========
spring:
datasource:
url: jdbc:mysql://prod-server.com:3306/prod_db
username: ${DB_USERNAME}
password: ${DB_PASSWORD}
hikari:
maximum-pool-size: 20
minimum-idle: 10
jpa:
hibernate:
ddl-auto: validate
show-sql: false
properties:
hibernate:
format_sql: false
jdbc:
batch_size: 50
fetch_size: 100
server:
port: 8443
ssl:
enabled: true
key-store: classpath:keystore.jks
key-store-password: ${SSL_PASSWORD}
Como Ativar um Perfil Específico
Em application.yml:
spring:
profiles:
active: dev # Ativa o perfil de desenvolvimento
Por linha de comando:
java -jar aplicacao.jar --spring.profiles.active=prod
Variável de ambiente:
export SPRING_PROFILES_ACTIVE=prod
java -jar aplicacao.jar
5. 🔨 Exemplo Prático Completo: Classe Entity com Spring Boot
Vamos criar uma classe Entity (Entidade) para ser persistida no banco de dados:
Pom.xml - Dependências Necessárias
<dependencies>
<!-- Spring Boot Data JPA -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- MySQL Driver -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
<!-- Spring Boot Web (REST) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Lombok (Optional - reduz código) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
Entidade Produto
package com.seu_nome.model;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Entity
@Table(name = "produtos")
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class Produto {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false, length = 100)
private String nome;
@Column(columnDefinition = "TEXT")
private String descricao;
@Column(nullable = false)
private Double preco;
@Column(nullable = false)
private Integer estoque;
@Column(nullable = false)
private Boolean ativo = true;
}
Repository (Acesso ao Banco)
package com.seu_nome.repository;
import com.seu_nome.model.Produto;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface ProdutoRepository extends JpaRepository<Produto, Long> {
// JpaRepository já fornece: save(), findById(), findAll(), delete(), etc.
// Métodos customizados
Iterable<Produto> findByNomeContainingIgnoreCase(String nome);
Iterable<Produto> findByPrecoLessThan(Double preco);
}
Service (Lógica de Negócio)
package com.seu_nome.service;
import com.seu_nome.model.Produto;
import com.seu_nome.repository.ProdutoRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Optional;
@Service
public class ProdutoService {
@Autowired
private ProdutoRepository produtoRepository;
// CRUD Operations
public Produto salvar(Produto produto) {
if (produto.getPreco() < 0) {
throw new IllegalArgumentException("Preço não pode ser negativo!");
}
return produtoRepository.save(produto);
}
public Optional<Produto> buscarPorId(Long id) {
return produtoRepository.findById(id);
}
public Iterable<Produto> buscarTodos() {
return produtoRepository.findAll();
}
public void deletar(Long id) {
produtoRepository.deleteById(id);
}
public Iterable<Produto> buscarPorNome(String nome) {
return produtoRepository.findByNomeContainingIgnoreCase(nome);
}
}
Controller (API REST)
package com.seu_nome.controller;
import com.seu_nome.model.Produto;
import com.seu_nome.service.ProdutoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/produtos")
public class ProdutoController {
@Autowired
private ProdutoService produtoService;
@PostMapping
public Produto criar(@RequestBody Produto produto) {
return produtoService.salvar(produto);
}
@GetMapping
public Iterable<Produto> listarTodos() {
return produtoService.buscarTodos();
}
@GetMapping("/{id}")
public Produto buscarPorId(@PathVariable Long id) {
return produtoService.buscarPorId(id)
.orElseThrow(() -> new RuntimeException("Produto não encontrado"));
}
@PutMapping("/{id}")
public Produto atualizar(@PathVariable Long id, @RequestBody Produto produtoAtualizado) {
Produto produto = produtoService.buscarPorId(id)
.orElseThrow(() -> new RuntimeException("Produto não encontrado"));
produto.setNome(produtoAtualizado.getNome());
produto.setPreco(produtoAtualizado.getPreco());
produto.setEstoque(produtoAtualizado.getEstoque());
return produtoService.salvar(produto);
}
@DeleteMapping("/{id}")
public void deletar(@PathVariable Long id) {
produtoService.deletar(id);
}
}
6. 🚀 Propriedades Avançadas de Configuração
Connection Pooling - HikariCP
HikariCP é o pool de conexões padrão do Spring Boot. Otimiza o gerenciamento de conexões:
spring:
datasource:
hikari:
# Número máximo de conexões no pool
maximum-pool-size: 20
# Número mínimo de conexões ociosais
minimum-idle: 5
# Tempo máximo para obter conexão (ms)
connection-timeout: 30000
# Tempo máximo que conexão fica inativa antes de ser testada (ms)
idle-timeout: 600000
# Tempo máximo de vida da conexão (ms)
max-lifetime: 1800000
# Validação de conexão
connection-test-query: SELECT 1
Propriedades Hibernate Úteis
spring:
jpa:
properties:
hibernate:
# Formatação do SQL
format_sql: true
# Comentários no SQL
use_sql_comments: true
# Batch size (aumento de performance)
jdbc:
batch_size: 20
fetch_size: 50
# Logging
generate_statistics: false
use_identifier_rollback: true
Logging e Debug
logging:
level:
root: INFO
org.springframework.web: DEBUG
org.springframework.security: DEBUG
org.hibernate.SQL: DEBUG
org.hibernate.type.descriptor.sql.BasicBinder: TRACE
pattern:
console: "%d{yyyy-MM-dd HH:mm:ss} - %msg%n"
file: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"
file:
name: logs/aplicacao.log
max-size: 10MB
max-history: 30
7. 🔐 Usando Variáveis de Ambiente
Nunca deixe senhas e dados sensíveis no código. Use variáveis de ambiente:
application.yml com Variáveis
spring:
datasource:
url: ${DB_URL:jdbc:mysql://localhost:3306/dev_db}
username: ${DB_USERNAME:root}
password: ${DB_PASSWORD:root123}
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
hibernate:
ddl-auto: ${DDL_AUTO:update}
Definindo Variáveis no Linux/Mac
# Arquivo .env ou .bashrc
export DB_URL="jdbc:mysql://prod-server.com:3306/banco"
export DB_USERNAME="usuario_prod"
export DB_PASSWORD="senha_super_segura"
export DDL_AUTO="validate"
# Executar a aplicação
java -jar app.jar
Arquivo .env (com dotenv)
# .env file
DB_URL=jdbc:mysql://localhost:3306/producao
DB_USERNAME=admin
DB_PASSWORD=senha_super_segura_aqui
DB_POOL_SIZE=20
ENVIRONMENT=production
8. 📊 Comparação: properties vs YAML
application.properties
- ✓ Formato tradicional
- ✓ Suporte amplo
- ✓ Simples para configs pequenas
- ✗ Repetitivo para estruturas aninhadas
application.yml
- ✓ Mais legível
- ✓ Suporta listas e maps
- ✓ Reduz redundância
- ✗ Sensível à indentação
Recomendação: Use YAML para novos projetos por sua melhor legibilidade e organização.
9. ✅ Boas Práticas
✓ FAÇA:
- Use @Transactional para operações críticas
- Configure pool de conexões adequadamente
- Use variáveis de ambiente para dados sensíveis
- Configure logging apropriadamente por ambiente
- Use DDL validate em produção
- Implemente versionamento de banco de dados (Flyway/Liquibase)
- Teste conexão ao iniciar (Actuator health)
✗ EVITE:
- Deixar senhas no código ou arquivo .properties
- Usar DDL create em produção
- Configurações hardcoded
- Mostrar SQL completo em produção
- Pool de conexões muito pequeno (<5)
- Pool de conexões muito grande (>50)
10. 🐛 Problemas Comuns e Soluções
❌ "Cannot get a connection, pool error"
Causa: Pool de conexões esgotado ou timeout excessivamente curto.
Solução: Aumente maximum-pool-size e connection-timeout. Implemente connection pooling adequado.
❌ "Communications link failure"
Causa: URL, host ou porta incorretos.
Solução: Verifique URL JDBC, teste conexão manualmente com banco.
❌ "Access denied for user"
Causa: Usuário ou senha incorretos.
Solução: Verifique credenciais, teste no cliente SQL do banco.
❌ "Table doesn't exist"
Causa: DDL-auto set incorretamente ou banco não criado.
Solução: Defina ddl-auto: update ou create em desenvolvimento.
11. 💪 Exercícios Práticos
Exercício 1: Configurar Aplicação com MySQL
Crie uma aplicação Spring Boot com entidade Usuario (id, nome, email, data_criacao). Configure arquivo application.yml para MySQL com pool de 10 conexões.
Exercício 2: Múltiplos Ambientes
Crie configurações para dev (H2), test (H2 em memória) e prod (MySQL). Ative diferentes perfis conforme necessário.
Exercício 3: Controller RESTful Completo
Implemente endpoints CRUD completos para entidade Produto com validações e tratamento de exceções.
Exercício 4: Variáveis de Ambiente
Configure aplicação para ler credenciais de banco via variáveis de ambiente. Teste localmente com arquivo .env.
Conclusão
O Spring Boot simplifica enormemente a conexão e gerenciamento de bancos de dados com application.properties e application.yml. Escolha entre properties ou yml (recomendamos YAML), configure corretamente para cada ambiente e use variáveis para dados sensíveis.
Lembre-se: properties/yml corretos + JPA + Repository = aplicação robusta e escalável!
Próximos passos: Explore segurança (Spring Security), cache (Redis), e testes automatizados!