Programando de forma simplificado com JDBC – Parte 1

Quase toda aplicação J2EE acessa dados de um banco de dados relacional. Por este motivo, o JDBC é  provavelmente uma das APIs mais populares disponíveis para a plataforma Java. O JDBC é conceitualmente simples e fácil de usar, mas para aplicações em produção, vários detalhes podem tornar o desenvolvimento do create/read/update/delete (CRUD) mais trivial em uma tarefa difícil. Embora muitos frameworks, ferramentas e APIs possam simplificar o desenvolvimento, estas são freqüentemente muito complexas. Como uma alternativa, este artigo apresenta um pequeno conjunto de classes fáceis de usar, manter e estender.

 

Você pode estar pensando: mais uma ferramenta/assistente/API/framework para complicar nossa vida? Posso entender sua hesitação: o problema de mapeamento objeto-relacional está sendo abordado faz anos. Todo mundo tem uma solução que é mais fácil, melhor, mais rápida e mais barata. Para que precisaríamos de mais código que provavelmente faz o que alguém já fez? Por duas razões: a maioria das soluções são geralmente mais complicadas do que o necessário e também demandam um compromisso significativo: uma vez que entramos, é difícil cair fora.

 

Gosto de coisas simples. Um colega citou recentemente uma frase interessante: "A simplicidade conduz à onipresença, a complexidade conduz a obscuridade". E todos têm ouvido a citação de Einstein: "Uma teoria científica deveria ser tão simples quanto possível, mas não a mais simples".

 

E esta é uma citação do James Gosling: "A complexidade é de muitas formas perniciosa. A complexidade torna as coisas mais difíceis de entender, mais difíceis de construir, mais difíceis de depurar, mais difíceis de evoluir, mais difícil de fazer tudo”.

 

Poderia continuar. Há muitos exemplos de complexidade, muitos. No caso de acesso a banco de dados, podemos utilizar entity beans, uma ferramenta de mapeamento objeto-relacional ou o mais recente framework open source. Não tenho reclamações formais contra quaisquer uma dessas ferramentas; tenho certeza de que os autores tiveram uma grande visão ao desenvolvê-las. Para mim, hoje, quero algo bem simples.

 

Voltemos um pouco no tempo. A maioria das vezes, uma aplicação precisa obter informação de um usuário e as criar/editar/deletar/visualizar como linhas em um banco de dados. Um detalhe importante é que a informação que vai e provém do usuário deve estar na forma de strings. Isto significa que a validação deve ser feita na entrada e a formatação na saída. Isto não é difícil, mas é repetitivo e envolve numerosas verificações desnecessárias. Outra característica importante que os usuários esperam ter é a habilidade para obter um conjunto grande de resultados ou pular para o fim de um conjunto de registros, nada fácil de obter com um ResultSet.

 

Uma solução popular é a de manualmente ou automaticamente mapear o SQL e esquemas resultantes de tabelas para objetos e classes. No início, isto parece razoável, se não natural. Em geral, modeladores de banco de dados e modeladores de objeto tentam realizar a mesma coisa: gerenciar a informação empresarial de uma maneira lógica e extensível.

 

Infelizmente, a lua de mel termina por aqui. Modeladores de objetos preferem se isolar dos vários detalhes quanto a como os dados são inseridos e recuperados. Para alguns, o banco de dados é como um grande hashmap com mais de uma chave. Esta poderia ser uma avaliação precisa, mas há a necessidade de uso de SQL conhecido como table join. Peritos de banco de dados argumentam que junções dão poder aos bancos de dados relacionais. Modeladores de objeto poderiam encará-los como algo que só causa mais dificuldades do que benefícios. Apesar das suas opiniões, objetos e bancos de dados provavelmente não irão mudar significativamente no futuro próximo. Aplicações e lógica de negócio continuarão usando objetos, e persistência de dados continuará tendo a forma de um banco de dados relacional.

 

Barreiras culturais aparte, existem diferenças significativas entre classes/objetos e linhas/tabelas. Objetos podem incluir comportamento, o que os distingue de estruturas e outros tipos de agregados. Classes oferecem herança e polimorfismo, o que as torna reutilizáveis e extensíveis. Mas bancos de dados têm a ver com armazenamento eficiente e procura rápida. Isso não pode ser subestimado quando são consideradas dezenas de milhares, se não milhões, de linhas de informação potenciais. Esta informação e o seu acesso de modo eficiente provam o quão importante é o código que irá fazer sua manipulação.

 

Outro detalhe importante é que classes são fáceis de mudar e o código é freqüentemente refatorado quando for conveniente e útil. Mudar a estrutura de um banco de dados representa um problema muito maior. Mudar nomes de colunas ou mesmo criar novas tabelas e recarregar dados não é em si mesmo um desafio, mas ajustar todo o código que suporta esta estrutura pode ser bem problemático. Por isso, tipicamente, tabelas de banco de dados mudam pouco depois que foram povoadas.

 

Todas estas diferenças conduziram à chamada impedância de casamento, um termo relativo ao princípio de máxima potência de transferência emprestado da engenharia elétrica. Embora possamos extrair e inserir dados fácil e eficazmente em um banco de dados, os objetos que usam os dados poderiam não se ajustar bem. O resultado típico é a ocorrência de muitos códigos que se assemelham à serialização manual de objetos. Isto é tedioso e propenso a erros.

 

Para evitar o tédio, muitas ferramentas evoluíram no decorrer dos anos. A especificação J2EE oferece um modelo na forma de container-managed entity beans e a EJB-QL (Enterprise JavaBean Query Language). Na comunidade open source, o Hibernate tem se tornado uma solução popular. Estas soluções dependem de uma linguagem de consulta como a SQL, mas não precisamente. O resultado é que poderíamos ter que ajustar as consultas para se ajustarem à ferramenta, em lugar de utilizar o que o banco de dados é capaz de fazer por si só.

 

Estas podem ser soluções efetivas para uma ampla gama de questões, mas ainda não satisfazem um padrão arbitrário de simplicidade. Dou ênfase à expressão arbitrário, porque muitos acharão que estas soluções satisfazem as exigências: é apenas uma diferença de opinião e nada mais.