Artigo no estilo Mentoring

Por que eu devo ler este artigo:Por meio de um exemplo que demonstra uma aplicação web desenvolvido com Hibernate e Spring, esse artigo expõe como algumas más práticas na implementação da camada de persistência passam despercebidas pela maioria dos desenvolvedores, causando problemas graves e erros catastróficos.

A partir disso, serão demonstradas aqui formas de evitar esses erros comuns e boas práticas na utilização de recursos do Hibernate que aprimoram o desempenho de aplicações e mitigam falhas recorrentes no projeto de software.

A camada de persistência das aplicações, independentemente da plataforma ou arquitetura adotadas, sempre são alvos de suspeitas no caso de problemas de desempenho, travamento, escalabilidade, etc.

Embora não necessariamente corretas, essas suspeitas são compreensíveis, dado o potencial destrutivo de bancos de dados mal configurados ou equivocadamente projetados e implementados. Por isso, não é absurdo afirmar que bancos de dados são vítimas históricas de más-práticas de projeto e implementação.

No entanto, a camada de persistência também tem sido objeto constante de pesquisa e desenvolvimento, o que vem resultando em diversas implementações interessantes.

No histórico dessas implementações achamos interfaces e padrões bastante populares, como o ADO, DAO, ODBC, o próprio JDBC, entre outros, destinados a enfrentar problemas clássicos na camada de persistência de aplicações.

Esses padrões foram bastante úteis a partir da popularização dos bancos de dados relacionais, ocorrida nos anos de 1970 a 1980, que fizeram surgir inúmeros métodos e linguagens para projetar e desenvolver o acesso a dados.

Foi nesse cenário que surgiu a linguagem SQL, já com o intuito de formar um padrão universalmente aceito e diminuir a proliferação exagerada de métodos de acesso aos sistemas gerenciadores de bancos de dados.

Sendo assim, uma vez que os problemas de isolamento da camada de persistência foram, de certa forma, assimilados, surgem na esteira da popularização crescente do desenvolvimento orientado a objetos os frameworks de mapeamento objeto-relacional, dentre os quais destacamos o Hibernate, que ocupa um papel de bastante importância no cenário mundial de desenvolvimento OO.

Apesar de serem acusados de produzir modelos de dados pobres ou mal normalizados devido ao alto nível de abstração em que os objetos geralmente são projetados – quando comparados com as tabelas do banco de dados – é correto afirmar que as técnicas de mapeamento objeto-relacional reduzem a quantidade de código e simplificam a tarefa de programação.

Com o Hibernate não é diferente, uma vez que ele fornece uma implementação que substitui o acesso direto às entidades da camada de persistência por operações de manipulação de objetos.

Com isso, o Hibernate – cujas primeiras versões foram lançadas no início dos anos 2000 – começa a ter seu uso massificado entre 2003 e 2005, período no qual ocorre a liberação do Hibernate 2 e a implementação da Java Persistence API 2 (JPA).

O Hibernate ORM é a ferramenta do projeto Hibernate que tem como objetivo fornecer uma implementação transparente para a correspondência entre os objetos da aplicação e a base de dados que irá persisti-los, simplificando a consulta ao banco de dados e livrando o desenvolvedor da tarefa de escrever a relação entre objetos da aplicação e as tabelas.

Com o Hibernate, os objetos do front-end da aplicação são construídos a partir de princípios da orientação a objetos, enquanto o back-end da aplicação seguirá conceitos e princípios de análise relacional e da normalização. Embora esses conceitos não sejam equivalentes, o mapeamento objeto-relacional implementado no Hibernate fornece os meios para a encontrar a compatibilidade necessária.

Apesar de toda a simplificação fornecida pelos recursos do Hibernate – e talvez causada por essa simplificação – não é raro se deparar com problemas causados por más-práticas de implementação ou erros na configuração do mesmo, principalmente quando seu desenvolvimento é realizado por desenvolvedores menos experientes ou sem fundamentos sólidos sobre os princípios de desenvolvimento OO e análise relacional.

Dessa forma, nesse artigo vamos demonstrar más-praticas bastante recorrentes no uso do Hibernate, que embora tenham soluções simples, ainda podem ser encontradas com bastante frequência, talvez devido a sua sutileza ou pelo fato de demandarem conhecimento sobre conceitos normalmente pouco aprofundados e específicos.

Explicando suas consequências e como evitá-las, exploraremos más-praticas responsáveis por algumas falhas graves em aplicações, com custo de resolução alto, além do desgaste desnecessário acarretado pelo retrabalho.

Sendo assim, o cenário demonstrado nesse artigo é composto por uma aplicação que apresenta problemas intermitentes. Neste cenário a aplicação funciona normalmente por algum tempo, mas tem seu funcionamento paralisado subitamente, sem causa aparente.

Além disso, exceções ocorrem de maneira caótica, sendo difícil relacionar os erros ocorridos com uma única causa.

Complicando ainda mais a busca por uma solução, os problemas são resolvidos temporariamente ao reiniciar a aplicação, voltando a ocorrer após algum tempo de uso. Este cenário será descrito com mais detalhes no próximo tópico desse artigo.

Ainda vale destacar que os casos apresentados no cenário brevemente descrito anteriormente ocorrem por dois motivos bastante comuns – não somente entre desenvolvedores Java, mas nas comunidades de desenvolvedores de qualquer arquitetura: mau uso ou má implementação do pool de conexões com o banco de dados (vide BOX 1); e mau projeto e implementação de associações entre classes no Hibernate.

BOX 1. Connection Pooling

É uma técnica utilizada para permitir que vários clientes façam uso de um conjunto compartilhado de conexões reusáveis com o banco de dados, reduzindo assim o custo associado ao uso dessas conexões e aumentando a performance do acesso à camada de persistência.

Ambos os problemas podem ser evitados ou resolvidos com medidas simples, muitas vezes fornecidas pelos próprios fabricantes dos frameworks utilizados, e amplamente documentadas.

Por isso, acreditamos que esse artigo é importante por fornecer uma descrição do caminho a seguir, exemplificando não somente boas e simples práticas para evitar problemas, mas contribuindo para abrir a mente do desenvolvedor e estimular o raciocínio a respeito de como aprimorar a qualidade do projeto de software, mitigando problemas desgastantes e destacando meios de enfrentá-los de maneira mais confortável.

Cenário: uma aplicação web com Hibernate e Spring

Nesse artigo, vamos utilizar como exemplo uma aplicação web em que o usuário é capaz de fazer a manutenção do cadastro de docentes de uma universidade. Esse exemplo foi construído utilizando, além do Hibernate ORM, o framework Spring para o desenvolvimento seguindo a arq ...

Quer ler esse conteúdo completo? Tenha acesso completo