Por que eu devo ler este artigo:Este artigo é útil por apresentar o Apache Cayenne, um mapeador objeto-relacional não aderente à especificação JPA. Integrado a uma poderosa ferramenta gráfica – o Cayenne Modeler – esta solução da Apache agrega agilidade e simplicidade ao desenvolvimento da camada de persistência de dados.

Sendo assim, desenvolvedores que buscam soluções voltadas para a persistência de dados podem encontrar no Apache Cayenne uma eficiente alternativa de ORM que abstrai qualquer necessidade de lidar com arquivos XML ou anotações durante o trabalho de mapeamento.

A necessidade de persistir dados em tempo de execução é tão antiga quanto a própria computação. De fato, a abordagem de gerenciar dados persistentes tem sido uma peça fundamental de decisão na concepção de todo projeto de software.

Notadamente, a aplicabilidade de um sistema cujos dados manipulados não sejam salvaguardados em algum formato ou estrutura contemplaria um escopo tão reduzido que a própria existência do sistema poderia ser objeto de questionamento.

Na perspectiva da plataforma Java, a persistência normalmente está associada ao armazenamento de dados em bancos de dados relacionais que fazem uso da linguagem SQL. No contexto deaplicações orientadas a objetos, a persistência possibilita que um objeto sobreviva à finalização do processo que o criou, uma vez que seu estado pode ser armazenado em disco, o que viabiliza a sua posterior recriação.

Naturalmente essa operação não é limitada a apenas um único objeto – todo um grafo de objetos pode da mesma forma ser persistido e subsequentemente recriado por meio de um novo processo.

Atualmente, grande parte dos projetos de softwares corporativos fazem uso conjugado do paradigma da orientação a objetos – para o desenvolvimento de aplicações – e da persistência em bancos de dados relacionais – para o armazenamento das informações.

Contudo, as diferenças existentes entre os fundamentos dessas duas abordagens inviabilizam uma perfeita adequação no uso concomitante de ambas. Isto porque enquanto o paradigma da orientação a objetos é baseado em princípios advindos da Engenharia de Software, o paradigma relacional, por outro lado, é baseado em fortes princípios matemáticos.

Logo, para que as duas abordagens possam coexistir em um mesmo projeto de sistema, é preciso preencher essa lacuna semântica (conhecida como Impedance Mismatch) que separa os dois paradigmas.

Uma técnica encontrada para contornar as especificidades que separam o mundo dos objetos do mundo das relações ficou conhecida como mapeamento objeto-relacional (Object-Relational Mapping – ORM). Em poucas palavras, um mapeamento objeto-relacional é um mecanismo de persistência baseado na tradução de objetos de uma aplicação para tabelas de um banco de dados relacional por meio de metadados que descrevem o mapeamento entre os objetos e o banco. Em essência, uma solução de ORM consiste em quatro peças principais:

· Uma API para executar operações básicas de CRUD (Create-Read-Update-Delete) sobre objetos de classes persistentes;

· Uma linguagem ou API para especificar queries que possam referenciar classes e suas respectivas propriedades;

· Uma forma de se construir mapeamentos por meio de metadados;

· Um mecanismo para que a implementação do ORM possa interagir com objetos transacionais a fim de executar a otimização de funções, como checagem de inconsistência de dados ou recuperação lazy de associações.

Alguns dos benefícios que podem ser derivados do uso de um mecanismo de ORM são:

· Produtividade: Boa parte do código relacionado com a camada de persistência de uma aplicação é substituída pelas funcionalidades da solução de ORM. Logo, desenvolvedores podem focar ainda mais nos problemas referentes ao negócio para o qual a aplicação está sendo construída;

· Manutenibilidade: Uma menor quantidade de linhas de código torna um sistema mais simples de se compreender, uma vez que o código existente está focado na lógica de negócio. Ainda mais importante é o fato de que sistemas com menos linhas de código são mais fáceis de serem refatorados.

Assim, dado que a persistência automatizada por uma solução de ORM reduz a quantidade de linhas de código de um sistema, então dela pode-se obter os ganhos citados anteriormente;

· Desempenho: Aclama-se que um código de persistência escrito diretamente pelo desenvolvedor da aplicação tem um desempenho pelo menos igual e, com frequência pode ter um desempenho superior, quando comparado ao código gerado e executado por um mecanismo de automatização de persistência.

Contudo, quando uma tarefa de persistência é analisada, sabe-se que diversas otimizações são passíveis de serem efetuadas. Algumas delas talvez sejam mais simples de implementar por meio de códigos construídos pelos próprios programadores.

Porém, muitas dessas otimizações são mais fáceis de serem alcançadas por meio de soluções automatizadas.

Além disso, equipes que implementam ORM provavelmente já desprenderam muito mais tempo investigando métricas de desempenho do que o tempo que qualquer desenvolvedor teria para estudar possíveis otimizações;

· Independência de fornecedores: Um mecanismo de ORM abstrai da aplicação as particularidades do banco de dados e do dialeto SQL usados. Se a ferramenta suporta um número diferente de bancos de dados, isso confere um certo nível de portabilidade à aplicação.

Logo, o desenvolvimento de um sistema multiplataforma torna-se usualmente mais simples quando há a utilização de uma solução de ORM. Além disso, ainda que operações multiplataforma não constituam um requisito para o sistema, o ORM pode auxiliar na mitigação de alguns dos riscos associados à dependência de fornecedores específicos.

Diante dos benefícios advindos da automatização das operações de persistência, diversas implementações de mecanismos de ORM surgiram. Na perspectiva da tecnologia Java, boa parte delas segue a especificação JPA.

Dentre os mais conhecidos estão Hibernate, TopLink e EclipseLink. Neste artigo, será apresentado uma solução de ORM que não segue a especificação JPA, o Apache Cayenne. Para exemplificar o uso da ferramenta, esta será utilizada para implementação da camada de persistência de uma aplicação web de exemplo.

Nota: A JPA (Java Persistence API) foi desenvolvida por um grupo de especialistas em EJB 3.0 como parte da JSR 220, porém não está limitada a componentes EJB. Ela provê um modelo de persistência de POJO que dá suporte ao desenvolvimento de aplicações independentes de soluções particulares de ORM.

O Apache Cayenne

O Apache Cayenne é um framework open source que provê um mecanismo de mapeamento objeto-relacional, além de serviços remotos auxiliares. Iniciado em 2001 e desde então, mantido pela comunidade, o projeto Cayenne possibilita a redução do tempo de desenvolvimento de aplicações cuja persistência é baseada em modelos relacionais, uma vez que cria uma abstração – orientada a objetos – das estruturas existentes em esquemas de bancos de dados.

Sua versão estável mais recente é a 3.0.2 (versão usada neste artigo). Porém, conta ainda com uma release candidate – versão 3.1 – e uma opção mais atual que encontra-se em fase de testes, a versão 3.2. Algumas das suas principais características são:

· Suporte tanto à engenharia reversa quanto à geração de bancos de dados;

· Engine de geração de classes baseada no Velocity;

· Mecanismo de caching;

· Completo conjunto de objetos voltados para a sintaxe de queries;

· Herança de objetos;

· Autodetecção de banco de dados;

· Capacidade de escalar projetos de qualquer dimensão para ambientes virtuais.

Notadamente, diversas características implementadas pelo Cayenne são comuns a outros mecanismos de ORM. Contudo, um relevante diferencial disponibilizado nesta solução é a possibilidade de ter todas as suas funções controladas diretamente via uma ferramenta com interface gráfica – o CayenneModeler.

De fato, esta última isenta o desenvolvedor da necessidade de lidar com quaisquer arquivos XML ou anotações durante a etapa de mapeamento objeto-relacional. Ressaltando ainda mais o potencial da ferramenta, por meio do CayenneModeler é possível que um completo esquema de banco de dados seja mapeado diretamente para objetos Java via interface gráfica.

Outra característica que distingue o framework Cayenne dos demais mecanismos de ORM relaciona-se com a sua arquitetura, a qual pode ser vista como a composição de duas grandes soluções de persistência:

· Cayenne Persistence API: API de propósito geral para mapeamentos objeto-relacionais. Internamente utiliza arquivos XML para descrição dos mapeamentos, porém estes arquivos podem ser abstraídos do desenvolvedor por meio da utilização da interface do CayenneModeler;

· Remote Object Persistence (ROP): É uma tecnologia que habilita o uso da API de persistência do Cayenne em aplicações-cliente remotas. Um uso comum do ROP é oferecer a aplicações SWT ou Swing um web service para acesso aos dados, em substituição ao acesso direto ao banco de dados.

Em casos como esses, um modelo abstrato de dados é compartilhado entre os dois lados – cliente e servidor.

Além do mecanismo de persistência propriamente dito, o Cayenne disponibiliza funcionalidades voltadas para o gerenciamento dos objetos persistíveis:

· Execução de queries: queries podem ser invocadas a fim de recuperar objetos que atendam a certos critérios. Outro aspecto é que objetos persistentes podem ser criados e preenchidos com valores provenientes do banco de dados;

· Chamada a um único método de Commit e Rollback: múltiplos objetos persistentes podem ter suas alterações gravadas no banco de dados por meio de uma única chamada de commit e dentro de uma única transação;

· Múltiplos níveis de Commit e Rollback aninhados: As funcionalidades de commit e rollback podem ter múltiplos níveis de aninhamento, isto é, um contexto pode executar o rollback de suas modificações sem afetar o “contexto-pai”.

De forma análoga, a execução do commit das alterações de um contexto não persiste no banco de dados as modificações do “contexto-pai”;

· Relacionamentos: O suporte a relacionamentos possibilita que objetos referenciados por um objeto recuperado possam ser acessados via uma única chamada simples de método. Por default, os relacionamentos não são recuperados juntos com os objetos.

Logo, em um relacionamento TO-MANY, os objetos referenciados são recuperados quando o tamanho da lista é solicitado ou quando o usuário tenta acessar um de seus elementos;

· Gerenciamento automático de relacionamentos bidirecionais: Se uma entidade A tem um relacionamento com a entidade B e, além disso, a entidade B tem um relacionamento com a entidade A, o Cayenne mantém a consistência do relacionamento reverso automaticamente.

A Listagem 1 dá uma visão do efeito que esse gerenciamento tem sobre o código. Naturalmente, esse recurso simplifica o gerenciamento de complexos grafos de objetos;

Listagem 1. Teste unitário para demonstração do gerenciamento de relacionamentos bidirecionais efetuado pelo Cayenne.


  Revista jm;
  Artigo cayenne;
  Artigo CayenneModeler;
   
  jm.setArtigo(cayenne);
  assertTrue(cayenne.getListOfRevista().contains(jm));
   
  jm.setArtigo(CayenneModeler);
  assertTrue(CayenneModeler.getListOfRevis ... 

Quer ler esse conteúdo completo? Tenha acesso completo