Especialização em Backend com Java & Spring Boot • Demonstrações Práticas Compiláveis


💻 Código de Exemplo 01 — Scripts de Migração Versionados com Flyway

-- src/main/resources/db/migration/V1__criar_tabela_usuarios.sql
CREATE TABLE usuarios (
    id BIGSERIAL PRIMARY KEY,
    nome VARCHAR(100) NOT NULL,
    email VARCHAR(255) NOT NULL UNIQUE,
    criado_em TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
-- src/main/resources/db/migration/V2__adicionar_coluna_status_usuarios.sql
ALTER TABLE usuarios ADD COLUMN status VARCHAR(20) NOT NULL DEFAULT 'ATIVO';
CREATE INDEX idx_usuarios_status ON usuarios (status);
# application.properties
spring.flyway.enabled=true
spring.flyway.locations=classpath:db/migration
spring.jpa.hibernate.ddl-auto=validate

💻 Código de Exemplo 02 — @Transactional com Propagation.REQUIRED e rollbackFor

package com.empresa.api.service;

import com.empresa.api.model.Pedido;
import com.empresa.api.repository.PedidoRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class PedidoService {

    private final PedidoRepository repository;
    private final EstoqueService estoqueService;

    public PedidoService(PedidoRepository repository, EstoqueService estoqueService) {
        this.repository = repository;
        this.estoqueService = estoqueService;
    }

    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public Pedido finalizar(Long pedidoId) throws EstoqueInsuficienteException {
        Pedido pedido = repository.findById(pedidoId)
            .orElseThrow(() -> new IllegalArgumentException("Pedido não encontrado"));

        estoqueService.reservarItens(pedido); // participa da mesma transação (REQUIRED)
        pedido.marcarComoFinalizado();

        return repository.save(pedido);
        // Se EstoqueInsuficienteException (checada) for lançada, rollbackFor garante
        // que o rollback ocorra mesmo não sendo RuntimeException.
    }
}
package com.empresa.api.service;

public class EstoqueInsuficienteException extends Exception {
    public EstoqueInsuficienteException(String mensagem) {
        super(mensagem);
    }
}

💻 Código de Exemplo 03 — Propagation.REQUIRES_NEW para Auditoria Isolada de Rollback

O log de auditoria deve sobreviver mesmo que a operação principal falhe depois — por isso roda em uma transação própria (REQUIRES_NEW), independente da transação que a chamou.

package com.empresa.api.service;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class AuditLogService {

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void registrarLog(String evento) {
        // Mesmo que o método chamador sofra rollback logo depois,
        // este INSERT já foi commitado em sua própria transação.
        System.out.println("LOG AUDITADO: " + evento);
    }
}
package com.empresa.api.service;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;

@Service
public class ContaService {

    private final AuditLogService auditLogService;

    public ContaService(AuditLogService auditLogService) {
        this.auditLogService = auditLogService;
    }

    // READ_COMMITTED evita dirty reads em operações financeiras concorrentes.
    @Transactional(isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class)
    public void debitar(Long id, BigDecimal valor) {
        auditLogService.registrarLog("Tentativa de débito de " + valor + " na conta " + id);

        if (valor.compareTo(BigDecimal.ZERO) <= 0) {
            throw new IllegalArgumentException("Valor de débito inválido");
            // A transação principal sofre rollback, mas o log acima já foi persistido.
        }
        // ... lógica de débito ...
    }
}