Quem mantem códigos JDBC puro?

Tenho curiosidade de saber se ainda existem muitos códigos JDBC puro.

Digo isso, pois mantenho um software JDBC e já cogitei convertê-lo para JPA, mas o trabalho seria enorme.
Principalmente pelo fato das chaves serem compostas.

Então desenvolvi um projeto simples pra auxiliar projetos JDBC e gostaria de saber se ainda existe público pra ele.

1 curtida

Cara, dá uma olhada nesse projeto: http://www.mybatis.org/mybatis-3/

Olha ai o que eu fiz. É bem simples mesmo

Olha, como exercício eu achei bem legal. Mas, como biblioteca para reuso, ainda teria que desenvolver muita coisa e melhorar outras. Acho, nesse caso, que o esforço não valeria a pena.

1 curtida

Desenvolvi baseado na necessidade do projeto. É bem simples. To lendo aqui sobre o MyBatis e é muita coisa.

Vou mostrar aqui como esse meu projeto ajudou no meu sistema:

Classe Original
/**
*
* @author krismorte
*/
public class AutorizaHoraExtraDao {

    public boolean insert(AutorizaHoraExtra model) {
        try {
            Connection con = ConnectionFactory.connectBase();
            String insert = "insert into hep_autoriza_hora_extra values(?,?,?,?,?)";
            PreparedStatement cmd = con.prepareStatement(insert);
            cmd.setString(1, model.getHoraExtra().getUsuario().getMatricula());
            cmd.setDate(2, new Date(model.getHoraExtra().getData().getMillis()));
            cmd.setDate(3, new Date(model.getDataAprovacao().getMillis()));
            cmd.setString(4, model.getJustificativa());
            cmd.setString(5, model.getAprovador().getMatricula());
            cmd.executeUpdate();
            cmd.close();
            con.close();
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            Main.addMsgLog(AutorizaHoraExtraDao.class.getName(), e.getMessage());
            return false;
        }
    }

    public boolean delete(String usuario, Date data) {
        try {
            Connection con = ConnectionFactory.connectBase();
            String insert = "delete from hep_autoriza_hora_extra where usuario=? and data=?";
            PreparedStatement cmd = con.prepareStatement(insert);
            cmd.setString(1, usuario);
            cmd.setDate(2, data);
            cmd.executeUpdate();
            cmd.close();
            con.close();
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            Main.addMsgLog(AutorizaHoraExtraDao.class.getName(), e.getMessage());
            return false;
        }
    }

    public AutorizaHoraExtra select(String usuarioMatricula, Date data) {
        try {
            Connection con = ConnectionFactory.connectBase();
            AutorizaHoraExtra lst = null;
            String select = "select hah.*,hu.matricula,hu.nome,hu.email,ha.matricula,ha.nome,ha.email,hhe.motivo,hhe.hora_entrada,"
                    + " hhe.hora_saida,hhe.hora_total , case when hhe.motivo is null then 'NÃO LANÇADA' else 'LANÇADA' end"
                    + " from hep_autoriza_hora_extra hah(nolock)"
                    + " left join hep_hora_extra hhe on hah.usuario=hhe.usuario and hah.data=hhe.data"
                    + " inner join hep_usuario hu on hah.usuario=hu.matricula"
                    + " inner join hep_usuario ha on hah.aprovador=ha.matricula"
                    + " where hah.usuario=? and hah.data=?";
            PreparedStatement cmd = con.prepareStatement(select);
            cmd.setString(1, usuarioMatricula);
            cmd.setDate(2, data);
            ResultSet set = cmd.executeQuery();
            if (set.next()) {
                Date d = set.getDate(2);
                Date d2 = set.getDate(3);
                UsuarioInterno usuario = new UsuarioInterno();
                usuario.setMatricula(set.getString(6));
                usuario.setNome(set.getString(7));
                usuario.setEmail(set.getString(8));
                UsuarioInterno aprovador = new UsuarioInterno();
                aprovador.setMatricula(set.getString(9));
                aprovador.setNome(set.getString(10));
                aprovador.setEmail(set.getString(11));
                lst = new AutorizaHoraExtra(usuario, new DateTime(d.getTime()), set.getString(12), set.getString(13), set.getString(14), set.getString(15), new DateTime(d2.getTime()), set.getString(4), aprovador, set.getString(16));
            }
            con.close();
            cmd.close();
            return lst;
        } catch (Exception e) {
            Main.addMsgLog(AutorizaHoraExtraDao.class.getName(), e.getMessage());
            return null;
        }
    }

    
    
     public List<AutorizaHoraExtra> list(int ano,int mes) {
        try {
            Connection con = ConnectionFactory.connectBase();
            List<AutorizaHoraExtra> lst = new ArrayList<AutorizaHoraExtra>();
            String select = "select hah.*,hu.matricula,hu.nome,hu.email,ha.matricula,ha.nome,ha.email,hhe.motivo,hhe.hora_entrada,"
                    + "hhe.hora_saida,hhe.hora_total , case when hhe.motivo is null then 'NÃO LANÇADA' else 'LANÇADA' end"
                    + " from hep_autoriza_hora_extra hah(nolock)"
                    + " left join hep_hora_extra hhe on hah.usuario=hhe.usuario and hah.data=hhe.data"
                    + " inner join hep_usuario hu on hah.usuario=hu.matricula"
                    + " inner join hep_usuario ha on hah.aprovador=ha.matricula"
                    + " where DATEPART(YEAR,hah.data)=? and DATEPART(MONTH,hah.data)=?";
            PreparedStatement cmd = con.prepareStatement(select);
            cmd.setInt(1, ano);
            cmd.setInt(2, mes);
            ResultSet set = cmd.executeQuery();
            while (set.next()) {
                Date d = set.getDate(2);
                Date d2 = set.getDate(3);
                UsuarioInterno usuario = new UsuarioInterno();
                usuario.setMatricula(set.getString(6));
                usuario.setNome(set.getString(7));
                usuario.setEmail(set.getString(8));
                UsuarioInterno aprovador = new UsuarioInterno();
                aprovador.setMatricula(set.getString(9));
                aprovador.setNome(set.getString(10));
                aprovador.setEmail(set.getString(11));
                lst.add(new AutorizaHoraExtra(usuario, new DateTime(d.getTime()), set.getString(12), set.getString(13), set.getString(14), set.getString(15), new DateTime(d2.getTime()), set.getString(4), aprovador, set.getString(16)));
            }
            con.close();
            cmd.close();
            return lst;
        } catch (Exception e) {
            e.printStackTrace();
            Main.addMsgLog(AutorizaHoraExtraDao.class.getName(), e.getMessage());
            return null;
        }
    }


    
    public List<AutorizaHoraExtra> list(Date ini, Date fim) {
        try {
            Connection con = ConnectionFactory.connectBase();
            List<AutorizaHoraExtra> lst = new ArrayList<AutorizaHoraExtra>();
            String select = "select hah.*,hu.matricula,hu.nome,hu.email,ha.matricula,ha.nome,ha.email,hhe.motivo,hhe.hora_entrada,"
                    + "hhe.hora_saida,hhe.hora_total , case when hhe.motivo is null then 'NÃO LANÇADA' else 'LANÇADA' end"
                    + " from hep_autoriza_hora_extra hah(nolock)"
                    + " left join hep_hora_extra hhe on hah.usuario=hhe.usuario and hah.data=hhe.data"
                    + " inner join hep_usuario hu on hah.usuario=hu.matricula"
                    + " inner join hep_usuario ha on hah.aprovador=ha.matricula"
                    + " where hah.data between ? and ?";
            PreparedStatement cmd = con.prepareStatement(select);
            cmd.setDate(1, ini);
            cmd.setDate(2, fim);
            ResultSet set = cmd.executeQuery();
            while (set.next()) {
                Date d = set.getDate(2);
                Date d2 = set.getDate(3);
                UsuarioInterno usuario = new UsuarioInterno();
                usuario.setMatricula(set.getString(6));
                usuario.setNome(set.getString(7));
                usuario.setEmail(set.getString(8));
                UsuarioInterno aprovador = new UsuarioInterno();
                aprovador.setMatricula(set.getString(9));
                aprovador.setNome(set.getString(10));
                aprovador.setEmail(set.getString(11));
                lst.add(new AutorizaHoraExtra(usuario, new DateTime(d.getTime()), set.getString(12), set.getString(13), set.getString(14), set.getString(15), new DateTime(d2.getTime()), set.getString(4), aprovador, set.getString(16)));
            }
            con.close();
            cmd.close();
            return lst;
        } catch (Exception e) {
            Main.addMsgLog(AutorizaHoraExtraDao.class.getName(), e.getMessage());
            return null;
        }
    }
}

Classe alterada

/**
 *
 * @author krismorte
 */
public class AutorizaHoraExtraDao extends EntidadeJDBC<AutorizaHoraExtra> {

    public static final Integer CONSULTA_POR_MES = 0;
    public static final Integer CONSULTA_POR_PERIODO = 1;
    public static final Integer INCLUIR_REGISTRO = 2;
    public static final Integer REMOVER_REGISTRO = 3;
    public static final Integer CONSULTA_POR_USUARIO_DATA = 4;

    private Connection conexao;

    public AutorizaHoraExtraDao() throws ExcecaoDao {
        super();
        adicionaComandoSQL(CONSULTA_POR_MES, "select hah.*,hu.matricula,hu.nome,hu.email,ha.matricula,ha.nome,ha.email,hhe.motivo,hhe.hora_entrada,"
                + "hhe.hora_saida,hhe.hora_total , case when hhe.motivo is null then 'NÃO LANÇADA' else 'LANÇADA' end"
                + " from hep_autoriza_hora_extra hah(nolock)"
                + " left join hep_hora_extra hhe on hah.usuario=hhe.usuario and hah.data=hhe.data"
                + " inner join hep_usuario hu on hah.usuario=hu.matricula"
                + " inner join hep_usuario ha on hah.aprovador=ha.matricula"
                + " where DATEPART(YEAR,hah.data)=? and DATEPART(MONTH,hah.data)=?");
        adicionaComandoSQL(CONSULTA_POR_PERIODO, "select hah.*,hu.matricula,hu.nome,hu.email,ha.matricula,ha.nome,ha.email,hhe.motivo,hhe.hora_entrada,"
                + "hhe.hora_saida,hhe.hora_total , case when hhe.motivo is null then 'NÃO LANÇADA' else 'LANÇADA' end"
                + " from hep_autoriza_hora_extra hah(nolock)"
                + " left join hep_hora_extra hhe on hah.usuario=hhe.usuario and hah.data=hhe.data"
                + " inner join hep_usuario hu on hah.usuario=hu.matricula"
                + " inner join hep_usuario ha on hah.aprovador=ha.matricula"
                + " where hah.data between ? and ?");
        adicionaComandoSQL(INCLUIR_REGISTRO, "insert into hep_autoriza_hora_extra values(?,?,?,?,?)");
        adicionaComandoSQL(REMOVER_REGISTRO, "delete from hep_autoriza_hora_extra where usuario=? and data=?");
        adicionaComandoSQL(CONSULTA_POR_USUARIO_DATA, "select hah.*,hu.matricula,hu.nome,hu.email,ha.matricula,ha.nome,ha.email,hhe.motivo,hhe.hora_entrada,"
                + " hhe.hora_saida,hhe.hora_total , case when hhe.motivo is null then 'NÃO LANÇADA' else 'LANÇADA' end"
                + " from hep_autoriza_hora_extra hah(nolock)"
                + " left join hep_hora_extra hhe on hah.usuario=hhe.usuario and hah.data=hhe.data"
                + " inner join hep_usuario hu on hah.usuario=hu.matricula"
                + " inner join hep_usuario ha on hah.aprovador=ha.matricula"
                + " where hah.usuario=? and hah.data=?");
        setExcecao(new ExceptionDao(AutorizaHoraExtraDao.class.getName()));
    }

@Override
    public Connection getConexao() {
        return ConnectionFactory.connectBase();
    }
  
    @Override
    public AutorizaHoraExtra consultar() throws ExcecaoDao {
        try {
            conexao = getConexao();
            AutorizaHoraExtra lst = null;

            ResultSet set = executaConsulta();
            if (set.next()) {
                Date d = set.getDate(2);
                Date d2 = set.getDate(3);
                UsuarioInterno usuario = new UsuarioInterno();
                usuario.setMatricula(set.getString(6));
                usuario.setNome(set.getString(7));
                usuario.setEmail(set.getString(8));
                UsuarioInterno aprovador = new UsuarioInterno();
                aprovador.setMatricula(set.getString(9));
                aprovador.setNome(set.getString(10));
                aprovador.setEmail(set.getString(11));
                lst = new AutorizaHoraExtra(usuario, new DateTime(d.getTime()), set.getString(12), set.getString(13), set.getString(14), set.getString(15), new DateTime(d2.getTime()), set.getString(4), aprovador, set.getString(16));
            }
            return lst;
        } catch (Exception e) {
            getExcecao().lancaExcecao(e);
            return null;
        } finally {
            finalizaConexaoComSeguranca(conexao);
        }
    }

    @Override
    public List listar() throws ExcecaoDao {
        try {
            List<AutorizaHoraExtra> lst = new ArrayList();
            conexao = getConexao();
            ResultSet set = executaConsulta();
            while (set.next()) {
                Date d = set.getDate(2);
                Date d2 = set.getDate(3);
                UsuarioInterno usuario = new UsuarioInterno();
                usuario.setMatricula(set.getString(6));
                usuario.setNome(set.getString(7));
                usuario.setEmail(set.getString(8));
                UsuarioInterno aprovador = new UsuarioInterno();
                aprovador.setMatricula(set.getString(9));
                aprovador.setNome(set.getString(10));
                aprovador.setEmail(set.getString(11));
                lst.add(new AutorizaHoraExtra(usuario, new DateTime(d.getTime()), set.getString(12), set.getString(13), set.getString(14), set.getString(15), new DateTime(d2.getTime()), set.getString(4), aprovador, set.getString(16)));
            }
            return lst;
        } catch (Exception e) {
            getExcecao().lancaExcecao(e);
            return null;
        } finally {
            finalizaConexaoComSeguranca(conexao);
        }
    }
}

Exemplo de Chamada

public boolean add() throws ExcecaoDao {
        EntidadeJDBC dao = new AutorizaHoraExtraDao();
        dao.escolherComandoSQL(AutorizaHoraExtraDao.INCLUIR_REGISTRO);
        dao.adicionaCampos(getHoraExtra().getUsuario().getMatricula(), new Date(getHoraExtra().getData().getMillis()),
                new Date(getDataAprovacao().getMillis()), getJustificativa(), getAprovador().getMatricula());
        dao.incluir();
        return true;
    }

Você teria sugestões de melhoria?

Eu vou mais longe, porque excluir do seu desenvolvimento JDBC, quando o mesmo é utilizado pelos ORM?

Claro, trabalhar com ORM é um ótima solução para não escrever muito código, padrão, etc, mas, nunca podemos esquecer que o JDBC é a base de tudo.

Então, não acho errado ter JDBC e também não acho errado usar ORM, tudo tem seus pros e contras e no mundo de desenvolvimento os dois podem trabalhar juntos.

Sempre digo isso, e se você tiver que dar manutenção em software legado com JDBC, não é melhor então saber do que excluir! é um ponto de vista.

2 curtidas

SIm, existem milhares de projetos espalhados por ai que ainda são em JDBC puro, normalmente projetos de 7 anos ou mais, estes são um pesadelos para os desenvolvedores, já passei por isso

Pelo que percebi, sua classe alterada acabou ficando com mais linhas de código do que usando JDBC puro. Além de que agora eu tenho que aprender a usar seu framework, enquanto qualquer programador ja sabe mexer com JDBC.

Em que exatamente seu framework auxilia?

ORM é ótimo se você tem um modelo de objetos simples pra ser mapeado em tabelas. Qualquer coisa mais complicada você vai ter que lutar com o framework.

A classe alterada ficou com mais linhas? Na verdade os métodos incluir/remover/atualizar foram removidos pois herdados e já estão implementados.

A minha ideia é diminuir as classes DAO e fazer reuso do que é comum. O que mais difere nas classes DAO são as consultas, pois os objetos devem ser montados. Já nos métodos incluir/remover/atualizar a preocupação é em montar o comando.

Tem razão, mas ainda é muito código pra algo que deveria ser trivial, como armazenar/recuperar informação do banco.
E toda essa concatenação de strings? Jesus.

Por que você esta dando a opção do desenvolvedor da aplicação apenas escolher a SQL? Por que ele não pode criar o SQL que ele quiser baseado nos requisitos da aplicação que ele esta desenvolvendo?

O @esmiralha me sugeriu o MyBites. É realmente bem mais completo e com isso pede bem mais configuração e todos os comandos SQL ficam em um arquivo XML. Eu meio que criei um meio termo entre o JDBC puro e algo mais organizado.

Utilizei a herança pra deixar alguns métodos comuns já implementados e exijo a implementação da conexão e dos métodos de consulta. Fica claro no exemplo que pus aqui que é necessário “registrar” todos os comandos que podem ser executados. Fica a cargo do que eu fiz montar os comandos e fechar as conexões.

Como eu disse criei isso baseado em um sistema que tenho onde seria muito mais trabalhoso convertê-lo totalmente para JPA.

Minha questão aqui é saber se ainda há muita gente na mesma situação que a minha (manter código antigo em JPA) e se o que eu fiz é interessante se pode melhorar e como. Enfim.

Estou aberto a sugestões :smiley:

Se eu entendi bem você tá sugerindo que eu criasse toda a instrução SQL?

Nesse caso eu acho que seria um tanto mais trabalhoso e fugiria ao que imaginei, já que teria que mapear Objetos - > Tabela e Atributos - > Campos

Ou isso é fácil de fazer e eu não sei?

Entendo. O problema é que na medida que o projeto cresce, você continua tendo que criar DAOs, e repetindo muito código dentro dos DAOs. Ou seja, isso não escala pra projetos complexos.
E para projetos simples eu imagino que as pessoas preferem usar uma ferramenta ORM.

O que você criou é o que geralmente é chamado de Query Helper. Nao chega a ser um ORM completo (como JPA), mas facilita lidar com JDBC diretamente.

Tem muita coisa pronta que já faz isso: o MyBatis já citado, JDBI, Spring Data JDBC extensions, jooq, entre outros.

Apesar de ser legal criar esse tipo de projeto, geralmente é mais fácil usar alguma coisa pronta e madura para resolver seu problema, por vários motivos:

  • Vários problemas que você nem encontrou ainda já foram solucionados
  • É muito mais fácil para seus colegas procurarem no google como fazer alguma coisa, do que terem que ler seu código
  • Geralmente possuem testes automatizados que previnem bugs a cada mudança.
  • Você tem mais tempo pra focar no negócio, resolver os problemas realmente importantes.
3 curtidas

Pra mim a vantagem de usar JDBC puro é justamente ter o controle total da queries, mas pra isso elas devem ficar o mais próximo das regras de negócio, portanto colocar em arquivos XML como o Mybatis, ou ocultas dentro de um DAO com o nome de CONSULTA_POR_MES não faz sentido.

Trabalho enorme e o sistema vai ficar mais pesado.

Em que sentido você diz que o sistema ficaria mais pesado.