Sistema de ServiçosJavaFX

Classe Java Tecnico Model

A classe Tecnico estende a classe Pessoa e adiciona um atributo específico: o salário. A seguir, vou descrever passo a passo o funcionamento dessa classe, explicando como ela utiliza herança e manipula os dados através de diferentes construtores e métodos.

1. Declaração da Classe

  • Herança: A classe Tecnico herda de Pessoa. Isso significa que todos os atributos e métodos definidos na classe Pessoa (como id, nome, email, etc.) estão disponíveis automaticamente na classe Tecnico.
  • Finalidade: A classe Tecnico é uma especialização de Pessoa que adiciona o atributo salario, permitindo a definição de técnicos dentro do sistema com todas as informações de uma pessoa mais o salário.
public class Tecnico extends Pessoa {
...
}

2. Atributo Específico de Tecnico

  • salario: Esse atributo armazena o salário do técnico, representado como um número decimal (Double).
  • Visibilidade private: O atributo é privado, o que significa que ele só pode ser acessado diretamente de dentro da classe Tecnico. O acesso externo a este atributo será feito através dos métodos getSalario() e setSalario().
private Double salario;

3. Construtor Padrão (Sem Argumentos)

  • Construtor Vazio: Esse construtor permite a criação de um objeto Tecnico sem a necessidade de passar parâmetros. Ele chama o construtor da classe Pessoa através da palavra-chave super(), o que significa que os atributos de Pessoa (como nome, email, etc.) serão inicializados com seus valores padrão.
  • Finalidade: Útil quando você deseja criar uma instância de Tecnico e definir os valores dos atributos posteriormente.
  •  
public Tecnico(){
    super();
}

4. Construtor Completo (Com Argumentos)

  • Uso de super: O construtor passa os primeiros parâmetros diretamente para o construtor da classe Pessoa através de super(). Isso inicializa os atributos herdados (id, nome, email, etc.).
  • this.salario: O salário é inicializado separadamente, já que ele é exclusivo da classe Tecnico.
  • Finalidade: Permite a criação de um objeto Tecnico já com todos os atributos, tanto os herdados de Pessoa quanto o atributo específico salario.
public Tecnico(Long id, String nome, String email, String senha, String cpf, Double salario, LocalDate dataCriacao) {
    super(id, nome, email, senha, cpf, dataCriacao);
    this.salario = salario;
}

5. Construtor com TecnicoDto(construiremos o DTO no futuro)

  • Construtor utilizando um DTO (Data Transfer Object): Esse construtor recebe um objeto da classe TecnicoDto, que geralmente é utilizado para transferir dados entre diferentes camadas da aplicação.
  • Uso de super com TecnicoDto: Os atributos herdados de Pessoa são inicializados utilizando os valores extraídos do objeto TecnicoDto. Para garantir que id não seja null, é utilizado um operador ternário: (tecnicoDto.getId() != null) ? tecnicoDto.getId() : null, o que define o id como null se ele não for fornecido no DTO.
  • Atributo salario: O valor do salário é obtido diretamente do tecnicoDto e atribuído ao atributo salario do objeto Tecnico.
  • Finalidade: Esse construtor facilita a criação de um objeto Tecnico a partir de dados recebidos em um formato mais simples (DTO), evitando a necessidade de passar cada atributo individualmente.
public Tecnico(TecnicoDto tecnicoDto) {
    super(
        (tecnicoDto.getId() != null) ? tecnicoDto.getId() : null,
        tecnicoDto.getNome(),
        tecnicoDto.getEmail(),
        tecnicoDto.getSenha(),
        tecnicoDto.getCpf(),
        tecnicoDto.getDataCriacao()
    );
    this.salario = tecnicoDto.getSalario();
}

6. Métodos de Acesso e Modificação (Getters e Setters)

  • getSalario(): Esse método permite acessar o valor do atributo salario. Ele é utilizado para retornar o valor atual do salário de um técnico.
  • Finalidade: Útil quando você precisa obter o salário de um técnico em outras partes da aplicação.
  • setSalario(Double salario): Esse método permite alterar o valor do atributo salario. O valor passado como argumento substitui o valor atual do salário.
  • Finalidade: Útil quando você precisa definir ou modificar o salário de um técnico.
public Double getSalario() {
    return salario;
}

public void setSalario(Double salario) {
    this.salario = salario;
}

7. Funcionamento Geral

A classe Tecnico herda todos os atributos e comportamentos comuns da classe Pessoa (como nome, email, cpf, etc.) e adiciona um novo atributo: salario. Ela permite a criação de objetos Tecnico de diferentes maneiras:

  • Através do construtor padrão (sem argumentos), que inicializa o técnico com valores padrão.
  • Através de um construtor completo, que inicializa todos os atributos, tanto os herdados de Pessoa quanto o salario.
  • Através de um construtor que recebe um TecnicoDto, facilitando a criação de técnicos a partir de objetos de transferência de dados.

A adição do atributo salario e a possibilidade de criar instâncias de Tecnico com diferentes abordagens fornecem flexibilidade à classe, permitindo seu uso em diversos cenários dentro da aplicação.

8. Conclusão

A classe Tecnico segue o princípio de herança da Orientação a Objetos, estendendo a funcionalidade da classe Pessoa ao adicionar o atributo salario. Ela é projetada de maneira que possa ser inicializada de diversas formas, com ou sem um DTO, e encapsula seu estado através de getters e setters, garantindo que o acesso ao atributo salario seja controlado e seguro.

9. O Código Completo deve ficar:

package br.com.professorclaytonandrade.sistemaservicojavafx.entity;

import br.com.professorclaytonandrade.sistemaservicojavafx.dto.TecnicoDto;
import javafx.util.converter.LocalDateStringConverter;

import java.time.LocalDate;

public class Tecnico extends Pessoa{
    private Double salario;

    public Tecnico(){
        super();
    }

    public Tecnico(Long id, String nome, String email, String senha, String cpf, Double salario, LocalDate dataCriacao) {
        super(id, nome, email, senha, cpf, dataCriacao);
        this.salario = salario;
    }

    public Tecnico(TecnicoDto tecnicoDto) {
        super(
            (tecnicoDto.getId() != null) ? tecnicoDto.getId() : null,
            tecnicoDto.getNome(),
            tecnicoDto.getEmail(),
            tecnicoDto.getSenha(),
            tecnicoDto.getCpf(),
            tecnicoDto.getDataCriacao()
        );
        this.salario = tecnicoDto.getSalario();
    }

    public Double getSalario() {
        return salario;
    }

    public void setSalario(Double salario) {
        this.salario = salario;
    }
}

Código Java Técnico DTO

A classe TecnicoDto é um DTO (Data Transfer Object), ou seja, um objeto de transferência de dados. Sua principal função é encapsular os dados do objeto Tecnico de forma simplificada para transporte entre diferentes camadas de uma aplicação. A seguir, descrevo o funcionamento detalhado dessa classe.

1. Declaração da Classe

Finalidade: A classe TecnicoDto representa uma simplificação dos dados de um objeto Tecnico, contendo apenas os atributos essenciais que serão manipulados. DTOs são frequentemente utilizados para transferir dados entre a camada de serviço e a camada de apresentação.
public class TecnicoDto {
....
}

2. Atributos da Classe

  • Atributos: Esses atributos representam os dados de um técnico que são relevantes para o sistema. Eles incluem o id, nome, email, senha, cpf, salario e dataCriacao. Cada atributo tem visibilidade privada, seguindo o princípio de encapsulamento.
private Long id;
private String nome;
private String email;
private String senha;
private String cpf;
private Double salario;
private LocalDate dataCriacao;

3. Construtor Completo

  • Validação: O construtor chama o método validarCampos() para garantir que os dados fornecidos para nome, email, senha, cpf, e salario estejam corretos e atendam aos critérios definidos. Isso previne que sejam criados objetos com dados inválidos.
  • Atribuição de Valores: Após a validação, os atributos são inicializados com os valores fornecidos.
public TecnicoDto(Long id, String nome, String email, String senha, String cpf, Double salario) {
    validarCampos(nome, email, senha, cpf, salario);
    this.id = id;
    this.nome = nome;
    this.email = email;
    this.senha = senha;
    this.cpf = cpf;
    this.salario = salario;
}

4. Construtor com Entidade Tecnico

  • Finalidade: Esse construtor recebe um objeto Tecnico e o converte em um TecnicoDto, extraindo os dados do objeto Tecnico e atribuindo-os ao DTO.
  • Validação: Assim como no primeiro construtor, os dados do tecnico são validados antes de serem atribuídos ao DTO.
  • Atributo dataCriacao: Ao contrário do construtor anterior, esse também inicializa o atributo dataCriacao, que é extraído do objeto Tecnico.
public TecnicoDto(Tecnico tecnico) {
    validarCampos(tecnico.getNome(), tecnico.getEmail(), tecnico.getSenha(), tecnico.getCpf(), tecnico.getSalario());
    this.id = tecnico.getId();
    this.nome = tecnico.getNome();
    this.email = tecnico.getEmail();
    this.senha = tecnico.getSenha();
    this.cpf = tecnico.getCpf();
    this.salario = tecnico.getSalario();
    this.dataCriacao = tecnico.getDataCriacao();
}

5. Métodos Getters e Setters

Os métodos get e set permitem acessar e modificar os valores dos atributos. Vou descrever cada um deles a seguir.

5.1 Getter e Setter

  • getId(): Retorna o valor atual do id.
  • setId(Long id): Atribui um novo valor para o id.
  • getNome(): Retorna o valor atual do nome.
  • setNome(String nome): Atribui um novo valor para o nome, validando antes de alterar o valor.
  • getEmail(): Retorna o valor atual do email.
  • setEmail(String email): Atribui um novo valor para o email, validando antes de alterar o valor.
  • getSenha(): Retorna o valor atual da senha.
  • setSenha(String senha): Atribui um novo valor para a senha, validando antes de alterar o valor.
  • getCpf(): Retorna o valor atual do cpf.
  • setCpf(String cpf): Atribui um novo valor para o cpf, validando antes de alterar o valor.
  • getSalario(): Retorna o valor atual do salario.
  • setSalario(Double salario): Atribui um novo valor para o salario.
  • getDataCriacao(): Retorna o valor atual da dataCriacao.
  • setDataCriacao(LocalDate dataCriacao): Atribui um novo valor para a dataCriacao.
public Long getId() {
    return id;
}

public void setId(Long id) {
    this.id = id;
}

public String getNome() {
    return nome;
}

public void setNome(String nome) {
    validarNome(nome);
    this.nome = nome;
}

public String getEmail() {
    return email;
}

public void setEmail(String email) {
    validarEmail(email);
    this.email = email;
}

public String getSenha() {
    return senha;
}

public void setSenha(String senha) {
    validarSenha(senha);
    this.senha = senha;
}

public String getCpf() {
    return cpf;
}

public void setCpf(String cpf) {
    validarCpf(cpf);
    this.cpf = cpf;
}

public Double getSalario() {
    return salario;
}

public void setSalario(Double salario) {
    this.salario = salario;
}

public LocalDate getDataCriacao() {
    return dataCriacao;
}

public void setDataCriacao(LocalDate dataCriacao) {
    this.dataCriacao = dataCriacao;
}

6. Métodos de Validação

A classe TecnicoDto tem diversos métodos estáticos que realizam a validação de seus atributos. Eles garantem que os dados sejam válidos antes de serem atribuídos ao objeto.

  • Validação de nome: Verifica se o nome não é nulo, vazio ou tem menos de 3 caracteres. Caso contrário, lança uma exceção.
  • Validação de email: Verifica se o email é válido conforme um padrão de regex (que assegura que o e-mail tenha um formato adequado).
  • Validação de senha: Verifica se a senha tem pelo menos 8 caracteres.
  • Validação de cpf: Verifica se o cpf contém exatamente 11 dígitos.
  • Validação de salario:Verifica se o salario não é nulo e é maior que zero.
  • Validação de Todos os Campos: Concentra todas as validações juntas para chamar no construtor uma única vez.
private static void validarNome(String nome) {
        if (nome == null || nome.trim().isEmpty()) {
            throw new IllegalArgumentException("O nome não pode ser vazio");
        } else if (nome.length() < 3) {
            throw new IllegalArgumentException("O nome deve conter pelo menos 3 caracteres");
        }
    }

    private static void validarEmail(String email) {
        if (email == null || email.trim().isEmpty()) {
            throw new IllegalArgumentException("O e-mail não pode ser vazio");
        } else if (!email.matches("^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+$")) {
            throw new IllegalArgumentException("E-mail inválido");
        }
    }

    private static void validarSenha(String senha) {
        if (senha == null || senha.trim().isEmpty()) {
            throw new IllegalArgumentException("A senha não pode ser vazia");
        } else if (senha.length() < 8) {
            throw new IllegalArgumentException("A senha deve ter pelo menos 8 caracteres");
        }
    }

    private static void validarCpf(String cpf) {
        if (cpf == null || cpf.trim().isEmpty()) {
            throw new IllegalArgumentException("O CPF não pode ser vazio");
        } else if (!cpf.matches("\\d{11}")) {
            throw new IllegalArgumentException("CPF inválido. Deve conter 11 dígitos numéricos");
        }
    }

    private static void validarSalario(Double salario) {
        if (salario == null) {
            throw new IllegalArgumentException("O salário não pode ser nulo");
        } else if (salario < 0) {
            throw new IllegalArgumentException("O salário deve ser maior que zero");
        }
    }

    private static void validarCampos(String nome, String email, String senha, String cpf, Double salario) {
        validarNome(nome);
        validarEmail(email);
        validarSenha(senha);
        validarCpf(cpf);
        validarSalario(salario);
    }

7. O Código Cpmleto deve ficar:

package br.com.professorclaytonandrade.sistemaservicojavafx.dto;

import br.com.professorclaytonandrade.sistemaservicojavafx.entity.Tecnico;

import java.time.LocalDate;

public class TecnicoDto {

    private Long id;
    private String nome;
    private String email;
    private String senha;
    private String cpf;
    private Double salario;
    private LocalDate dataCriacao;


    public TecnicoDto(Long id, String nome, String email, String senha, String cpf, Double salario) {
        validarCampos(nome, email, senha, cpf, salario);
        this.id = id;
        this.nome = nome;
        this.email = email;
        this.senha = senha;
        this.cpf = cpf;
        this.salario = salario;
    }

    public TecnicoDto(Tecnico tecnico) {
        validarCampos(tecnico.getNome(), tecnico.getEmail(), tecnico.getSenha(), tecnico.getCpf(), tecnico.getSalario());
        this.id = tecnico.getId();
        this.nome = tecnico.getNome();
        this.email = tecnico.getEmail();
        this.senha = tecnico.getSenha();
        this.cpf = tecnico.getCpf();
        this.salario = tecnico.getSalario();
        this.dataCriacao = tecnico.getDataCriacao();
     }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        validarNome(nome);
        this.nome = nome;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        validarEmail(email);
        this.email = email;
    }

    public String getSenha() {
        return senha;
    }

    public void setSenha(String senha) {
        validarSenha(senha);
        this.senha = senha;
    }

    public String getCpf() {
        return cpf;
    }

    public void setCpf(String cpf) {
        validarCpf(cpf);
        this.cpf = cpf;
    }

    public Double getSalario() {
        return salario;
    }

    public void setSalario(Double salario) {
        this.salario = salario;
    }

    public LocalDate getDataCriacao() {
        return dataCriacao;
    }

    public void setDataCriacao(LocalDate dataCriacao) {
        this.dataCriacao = dataCriacao;
    }

    private static void validarNome(String nome) {
        if (nome == null || nome.trim().isEmpty()) {
            throw new IllegalArgumentException("O nome não pode ser vazio");
        } else if (nome.length() < 3) {
            throw new IllegalArgumentException("O nome deve conter pelo menos 3 caracteres");
        }
    }

    private static void validarEmail(String email) {
        if (email == null || email.trim().isEmpty()) {
            throw new IllegalArgumentException("O e-mail não pode ser vazio");
        } else if (!email.matches("^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+$")) {
            throw new IllegalArgumentException("E-mail inválido");
        }
    }

    private static void validarSenha(String senha) {
        if (senha == null || senha.trim().isEmpty()) {
            throw new IllegalArgumentException("A senha não pode ser vazia");
        } else if (senha.length() < 8) {
            throw new IllegalArgumentException("A senha deve ter pelo menos 8 caracteres");
        }
    }

    private static void validarCpf(String cpf) {
        if (cpf == null || cpf.trim().isEmpty()) {
            throw new IllegalArgumentException("O CPF não pode ser vazio");
        } else if (!cpf.matches("\\d{11}")) {
            throw new IllegalArgumentException("CPF inválido. Deve conter 11 dígitos numéricos");
        }
    }

    private static void validarSalario(Double salario) {
        if (salario == null) {
            throw new IllegalArgumentException("O salário não pode ser nulo");
        } else if (salario < 0) {
            throw new IllegalArgumentException("O salário deve ser maior que zero");
        }
    }

    private static void validarCampos(String nome, String email, String senha, String cpf, Double salario) {
        validarNome(nome);
        validarEmail(email);
        validarSenha(senha);
        validarCpf(cpf);
        validarSalario(salario);
    }
}

Código Java TecnicoDAO (Data Access Object)

O código da classe TecnicoDao implementa um Data Access Object (DAO) para a entidade Tecnico, responsável por executar operações no banco de dados, como inserir, listar, atualizar, excluir e buscar técnicos. Aqui está uma explicação detalhada de cada parte:

1. Logger

  • O Logger é utilizado para registrar informações sobre as operações realizadas no banco de dados, como sucesso ou falhas. Ele auxilia no monitoramento e depuração de erros.
private static final Logger logger = LoggerFactory.getLogger(TecnicoDao.class);

2. Método inserir(Tecnico tecnico)

  • Este método insere um técnico no banco de dados. Ele zera o ID do técnico (pois será gerado automaticamente pelo banco). A conexão com o banco é obtida através da FabricaDeConexao, e o PreparedStatement é usado para prevenir injeções SQL.
  • Campos como nome, email, senha, CPF, salário e data de criação são inseridos.
  • Caso a inserção seja bem-sucedida, o método retorna true e um log de sucesso é gerado.
public boolean inserir(Tecnico tecnico) {
        boolean isInserido = false; // Variável para armazenar o status da inserção

        tecnico.setId(null);
        String sql = "INSERT INTO tecnico (nome, email, senha, cpf, salario, data_criacao) 
                        VALUES (?, ?, ?, ?, ?, ?)";

        try (Connection conexao = FabricaDeConexao.obterConexao();
             PreparedStatement statement = conexao.prepareStatement(sql)) {

            statement.setString(1, tecnico.getNome());
            statement.setString(2, tecnico.getEmail());
            statement.setString(3, tecnico.getSenha());
            statement.setString(4, tecnico.getCpf());
            statement.setDouble(5, tecnico.getSalario());
            statement.setDate(6, Date.valueOf(tecnico.getDataCriacao()));

            int linhasAfetadas = statement.executeUpdate();
            if (linhasAfetadas > 0) {
                isInserido = true; // A inserção foi bem-sucedida
                logger.info("Técnico inserido com sucesso: {}", tecnico.getNome());
            }

        } catch (SQLException e) {
            logger.error("Erro ao inserir técnico: {}", e.getMessage());
        }
        return isInserido; // Retorna o status da inserção
    }

3. Método listar()

  • Este método retorna uma lista de todos os técnicos armazenados no banco de dados.
  • Ele executa um SELECT * FROM tecnico para recuperar todos os registros da tabela e os armazena em uma lista de objetos Tecnico. Cada linha do resultado é mapeada para um objeto Tecnico.
public List listar() {
        List tecnicos = new ArrayList<>();
        String sql = "SELECT * FROM tecnico";

        try (Connection conexao = FabricaDeConexao.obterConexao();
             PreparedStatement statement = conexao.prepareStatement(sql);
             ResultSet resultado = statement.executeQuery()) {

            while (resultado.next()) {
                Tecnico tecnico = new Tecnico();
                tecnico.setId(resultado.getLong("id"));
                tecnico.setNome(resultado.getString("nome"));
                tecnico.setEmail(resultado.getString("email"));
                tecnico.setSenha(resultado.getString("senha"));
                tecnico.setCpf(resultado.getString("cpf"));
                tecnico.setSalario(resultado.getDouble("salario"));
                tecnico.setDataCriacao(resultado.getDate("data_criacao") != null ? resultado.getDate("data_criacao").toLocalDate() : null);

                tecnicos.add(tecnico);
            }
            logger.info("Lista de técnicos recuperada com sucesso.");

        } catch (SQLException e) {
            logger.error("Erro ao listar técnicos: {}", e.getMessage());
        }
        return tecnicos;
    }

4. Método atualizar(Tecnico tecnico)

  • Atualiza os dados de um técnico já existente no banco de dados.
  • O ID do técnico não pode ser nulo, pois é necessário para identificar qual registro será atualizado. Campos como nome, email, senha, CPF, salário são atualizados com os novos valores fornecidos.
  • O método retorna true se a atualização for bem-sucedida e gera um log informando o sucesso.
public boolean atualizar(Tecnico tecnico) {
        boolean isInserido = false; // Variável para armazenar o status da inserção

        if (tecnico.getId() == null) {
            logger.warn("ID do técnico não pode ser nulo. Atualização não realizada.");
            throw new IllegalArgumentException("ID do técnico não pode ser nulo.");
        }

        String sql = "UPDATE tecnico 
                SET nome = ?, email = ?, senha = ?, cpf = ?, salario = ? 
                WHERE id = ?";

        try (Connection conexao = FabricaDeConexao.obterConexao();
             PreparedStatement statement = conexao.prepareStatement(sql)) {

            statement.setString(1, tecnico.getNome());
            statement.setString(2, tecnico.getEmail());
            statement.setString(3, tecnico.getSenha());
            statement.setString(4, tecnico.getCpf());
            statement.setDouble(5, tecnico.getSalario());
            statement.setLong(6, tecnico.getId());

            int linhasAfetadas = statement.executeUpdate();
            if (linhasAfetadas > 0) {
                isInserido = true; // A atualização foi bem-sucedida
                logger.info("Técnico atualizado com sucesso: {}", tecnico.getId());
            }

        } catch (SQLException e) {
            logger.error("Erro ao atualizar técnico: {}", e.getMessage());
        }
        return isInserido;
    }

5. Método excluir(Long id)

  • Exclui um técnico do banco de dados com base no ID fornecido.
  • Executa um DELETE FROM tecnico WHERE id = ?. Se a operação for bem-sucedida, um log informando a exclusão é gerado.
public void excluir(Long id) {
        String sql = "DELETE FROM tecnico WHERE id = ?";

        try (Connection conexao = FabricaDeConexao.obterConexao();
             PreparedStatement statement = conexao.prepareStatement(sql)) {

            statement.setLong(1, id);
            statement.executeUpdate();
            logger.info("Técnico excluído com sucesso: {}", id);

        } catch (SQLException e) {
            logger.error("Erro ao excluir técnico: {}", e.getMessage());
        }
    }

6. Método buscarPorId(Long id)

  • Busca um técnico específico no banco de dados pelo ID.
  • Se o técnico for encontrado, os dados são armazenados em um objeto Tecnico e retornados. Se nenhum técnico for encontrado, retorna null e um log avisa que o técnico não foi encontrado.
public Tecnico buscarPorId(Long id) {
        Tecnico tecnico = null;
        String sql = "SELECT id, nome, email, senha, cpf, salario, data_criacao 
                        FROM tecnico WHERE id = ?";

        try (Connection conexao = FabricaDeConexao.obterConexao();
             PreparedStatement statement = conexao.prepareStatement(sql)) {

            statement.setLong(1, id);
            ResultSet resultado = statement.executeQuery();

            if (resultado.next()) {
                tecnico = new Tecnico();
                tecnico.setId(resultado.getLong("id"));
                tecnico.setNome(resultado.getString("nome"));
                tecnico.setEmail(resultado.getString("email"));
                tecnico.setSenha(resultado.getString("senha"));
                tecnico.setCpf(resultado.getString("cpf"));
                tecnico.setSalario(resultado.getDouble("salario"));
                tecnico.setDataCriacao(resultado.getDate("data_criacao").toLocalDate());
                logger.info("Técnico encontrado: {}", tecnico.getNome());
            } else {
                logger.warn("Nenhum técnico encontrado com o ID: {}", id);
            }

        } catch (SQLException e) {
            logger.error("Erro ao buscar técnico por ID: {}", e.getMessage());
        }
        return tecnico;
    }

7. Estrutura de Conexão

  • Todos os métodos de interação com o banco de dados utilizam try-with-resources para garantir que os recursos (conexões, PreparedStatement, e ResultSet) sejam fechados automaticamente após a execução, evitando vazamento de recursos.
  • try-with-resources foi introduzido no Java 7 e permite que qualquer recurso que implemente a interface AutoCloseable (como Connection, PreparedStatement, e ResultSet) seja automaticamente fechado quando o bloco try é concluído. Isso evita a necessidade de fechar esses recursos manualmente no bloco finally, reduzindo o risco de vazamento de recursos, o que pode causar problemas de desempenho e exaustão de conexões.

Conclusão

Essa classe centraliza as operações CRUD (Create, Read, Update, Delete) para a entidade Tecnico, utilizando uma abordagem segura com logs e validações, além de uma conexão com o banco de dados gerenciada automaticamente pela FabricaDeConexao.

Código Completo:

package br.com.professorclaytonandrade.sistemaservicojavafx.dao;

import br.com.professorclaytonandrade.sistemaservicojavafx.config.conexao.FabricaDeConexao;
import br.com.professorclaytonandrade.sistemaservicojavafx.entity.Tecnico;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class TecnicoDao {

    private static final Logger logger = LoggerFactory.getLogger(TecnicoDao.class);

    // Método para inserir um técnico no banco de dados
    public boolean inserir(Tecnico tecnico) {
        boolean isInserido = false; // Variável para armazenar o status da inserção

        tecnico.setId(null);
        String sql = "INSERT INTO tecnico (nome, email, senha, cpf, salario, data_criacao) 
                VALUES (?, ?, ?, ?, ?, ?)";

        try (Connection conexao = FabricaDeConexao.obterConexao();
             PreparedStatement statement = conexao.prepareStatement(sql)) {

            statement.setString(1, tecnico.getNome());
            statement.setString(2, tecnico.getEmail());
            statement.setString(3, tecnico.getSenha());
            statement.setString(4, tecnico.getCpf());
            statement.setDouble(5, tecnico.getSalario());
            statement.setDate(6, Date.valueOf(tecnico.getDataCriacao()));

            int linhasAfetadas = statement.executeUpdate();
            if (linhasAfetadas > 0) {
                isInserido = true; // A inserção foi bem-sucedida
                logger.info("Técnico inserido com sucesso: {}", tecnico.getNome());
            }

        } catch (SQLException e) {
            logger.error("Erro ao inserir técnico: {}", e.getMessage());
        }
        return isInserido; // Retorna o status da inserção
    }

    // Método para listar todos os técnicos
    public List listar() {
        List tecnicos = new ArrayList<>();
        String sql = "SELECT * FROM tecnico";

        try (Connection conexao = FabricaDeConexao.obterConexao();
             PreparedStatement statement = conexao.prepareStatement(sql);
             ResultSet resultado = statement.executeQuery()) {

            while (resultado.next()) {
                Tecnico tecnico = new Tecnico();
                tecnico.setId(resultado.getLong("id"));
                tecnico.setNome(resultado.getString("nome"));
                tecnico.setEmail(resultado.getString("email"));
                tecnico.setSenha(resultado.getString("senha"));
                tecnico.setCpf(resultado.getString("cpf"));
                tecnico.setSalario(resultado.getDouble("salario"));
                tecnico.setDataCriacao(resultado.getDate("data_criacao") != null ? 
                    resultado.getDate("data_criacao").toLocalDate() : null);

                tecnicos.add(tecnico);
            }
            logger.info("Lista de técnicos recuperada com sucesso.");

        } catch (SQLException e) {
            logger.error("Erro ao listar técnicos: {}", e.getMessage());
        }
        return tecnicos;
    }

    // Método para atualizar um técnico no banco de dados
    public boolean atualizar(Tecnico tecnico) {
        boolean isInserido = false; // Variável para armazenar o status da inserção

        if (tecnico.getId() == null) {
            logger.warn("ID do técnico não pode ser nulo. Atualização não realizada.");
            throw new IllegalArgumentException("ID do técnico não pode ser nulo.");
        }

        String sql = "UPDATE tecnico SET nome = ?, email = ?, senha = ?, cpf = ?, salario = ? 
            WHERE id = ?";

        try (Connection conexao = FabricaDeConexao.obterConexao();
             PreparedStatement statement = conexao.prepareStatement(sql)) {

            statement.setString(1, tecnico.getNome());
            statement.setString(2, tecnico.getEmail());
            statement.setString(3, tecnico.getSenha());
            statement.setString(4, tecnico.getCpf());
            statement.setDouble(5, tecnico.getSalario());
            statement.setLong(6, tecnico.getId());

            int linhasAfetadas = statement.executeUpdate();
            if (linhasAfetadas > 0) {
                isInserido = true; // A atualização foi bem-sucedida
                logger.info("Técnico atualizado com sucesso: {}", tecnico.getId());
            }

        } catch (SQLException e) {
            logger.error("Erro ao atualizar técnico: {}", e.getMessage());
        }
        return isInserido;
    }

    // Método para excluir um técnico do banco de dados
    public void excluir(Long id) {
        String sql = "DELETE FROM tecnico WHERE id = ?";

        try (Connection conexao = FabricaDeConexao.obterConexao();
             PreparedStatement statement = conexao.prepareStatement(sql)) {

            statement.setLong(1, id);
            statement.executeUpdate();
            logger.info("Técnico excluído com sucesso: {}", id);

        } catch (SQLException e) {
            logger.error("Erro ao excluir técnico: {}", e.getMessage());
        }
    }

    // Método para buscar um técnico pelo ID
    public Tecnico buscarPorId(Long id) {
        Tecnico tecnico = null;
        String sql = "SELECT id, nome, email, senha, cpf, salario, data_criacao FROM tecnico 
            WHERE id = ?";

        try (Connection conexao = FabricaDeConexao.obterConexao();
             PreparedStatement statement = conexao.prepareStatement(sql)) {

            statement.setLong(1, id);
            ResultSet resultado = statement.executeQuery();

            if (resultado.next()) {
                tecnico = new Tecnico();
                tecnico.setId(resultado.getLong("id"));
                tecnico.setNome(resultado.getString("nome"));
                tecnico.setEmail(resultado.getString("email"));
                tecnico.setSenha(resultado.getString("senha"));
                tecnico.setCpf(resultado.getString("cpf"));
                tecnico.setSalario(resultado.getDouble("salario"));
                tecnico.setDataCriacao(resultado.getDate("data_criacao").toLocalDate());
                logger.info("Técnico encontrado: {}", tecnico.getNome());
            } else {
                logger.warn("Nenhum técnico encontrado com o ID: {}", id);
            }

        } catch (SQLException e) {
            logger.error("Erro ao buscar técnico por ID: {}", e.getMessage());
        }
        return tecnico;
    }
}