JAVA Learning

Hub de Conteúdo

🗄️ 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

properties
# ========== 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

properties
# ========== 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)

properties
# ========== 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

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

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

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)

yaml
# ========== 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)

yaml
# ========== 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:

yaml
spring:
  profiles:
    active: dev  # Ativa o perfil de desenvolvimento

Por linha de comando:

bash
java -jar aplicacao.jar --spring.profiles.active=prod

Variável de ambiente:

bash
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

xml
<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

java
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)

java
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)

java
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)

java
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:

yaml
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

yaml
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

yaml
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

yaml
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

bash
# 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
# .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!