t-com:office:office" />

Explorando técnicas e tecnologias para persistência de dados

Conheça as três principais escolas para o acesso e a persistência de dados, e as vantagens e desvantagens de cada uma, enfocando o estado-da-arte em tecnologias Java

Um dos principais problemas do desenvolvimento de software, nos últimos 15 anos, quando começou a popularização da Orientação a Objetos, tem sido a compatibilização entre este paradigma e o dos bancos de dados relacionais. Já conhecemos bem a história: objetos versus tabelas; herança versus joins, encapsulamento versus projeção, e assim por diante.

O problema é resumido pela Figura 1, onde vemos uma aplicação OO escrita em Java acessando um SGBD relacional. A "Interface BDR" é a interface natural, ou "nativa", do SGBD. Para bancos relacionais, essa interface é uma combinação entre SQL e estruturas de dados e protocolos de rede otimizados para executar comandos SQL e transferir dados tabulares. O JDBC é um exemplo de API modelada segundo os requisitos destas estruturas e protocolos.

 

Figura 1. Aplicação OO Java acessando um banco relacional, com a necessidade de mapear os objetos para o mundo relacional (sombreado = overhead).

 

A aplicação OO precisará de uma camada de "mapeamento objeto-relacional", que traduz estruturas e operações do mundo OO para o mundo relacional. Embora o termo "mapeamento" seja mais usado com ferramentas que fazem isso automaticamente, toda vez que você escreve, por exemplo, um código JDBC que executa um SELECT ... FROM CLIENTE e extrai os resultados retornados para seus objetos Cliente, está fazendo mapeamento objeto-relacional, só que à mão.

Escrever esse código à mão é obviamente trabalhoso, então qual é a solução para combinar uma linguagem OO com um SGBD? Muitos desenvolvedores Java que utilizam ferramentas como o Hibernate, JDO, ou a nova JPA do EJB 3.0, podem considerar este problema já resolvido. A resposta estaria nas já citadas ferramentas de mapeamento objeto-relacional (ORM). Todavia, esta resposta se baseia em três pressupostos que podem não ser verdadeiros para todos os desenvolvedores e todos os projetos:

1.      Uma "grande unificação OO" é melhor que misturar paradigmas;

2.      Todos os SGBDs acessados são estritamente relacionais;

3.      Ferramentas ORM acessam os dados da forma mais eficiente e produtiva.

 

Neste artigo, vamos explorar a questão do acesso a SGBDs, revisando diversas escolas de pensamento, e examinando as principais alternativas tanto em Java quanto em algumas outras linguagens e plataformas. Nosso plano é o de informar o leitor sobre todo o panorama das técnicas de acesso a dados. O objetivo é ajudá-lo a navegar pela multidão de ferramentas e tecnologias que competem pela fidelidade dos desenvolvedores.

Escola 1: Bancos OO

A primeira escola que abordaremos é a dos puristas OO – abandonar o paradigma relacional e utilizar bancos de dados OO puros ou, pelo menos BDs híbridos OO/relacionais. Neste caso, o banco de dados fala a língua dos objetos e tudo está resolvido, a favor do paradigma orientado a objetos.

Um banco puramente OO armazena dados organizados em hierarquias de classes, não em tabelas. Bancos OO suportam diretamente herança, polimorfismo e coleções. E suportam uma linguagem OO para consultas e para procedimentos armazenados (stored procedures). A Figura 2 mostra a arquitetura resultante. Esta arquitetura é mais simples que a da Figura 1, pois não precisamos de nenhum mapeamento, já que o banco de dados já "fala" a linguagem dos objetos – a interface de acesso ao BD é uma interface OO. Isso significa que não podemos usar nem SQL, nem JDBC, para acessar o BD, mas precisamos substituir essas tecnologias por linguagens de consultas (query languages) e APIs apropriadas ao SGBD.

Além da simplicidade (ex.: não ter que especificar nenhum mapeamento), temos também um desempenho potencialmente superior, pois não precisamos executar uma camada adicional de código de mapeamento. E tudo o mais sendo igual, quanto menos código você precisar para determinada tarefa, menos CPU estará gastando.

SGBDOOs e o padrão JDO

Um grande problema dos SGBDOOs, tradicionalmente, era a falta de padrões. Até há alguns anos, a regra era linguagens de consultas e APIs proprietárias e diferentes de um BDOO para outro. Ou seja, no lugar daquela caixinha "Interface BDOO" da Figura 2, poderíamos ler "API proprietária e não-portável". Algo especialmente ruim na comunidade Java, que valoriza a padronização e a portabilidade.

Por exemplo, com o banco db4o (que tem uma versão GPL), teremos código como o da Listagem 1 (baseada no exemplo "Formula 1" do tutorial deste banco). A classe ObjectContainer representa a conexão com a base de dados. Para localizar todos os objetos Pilot com um nome específico, criamos um objeto deste tipo (um POJO) setando somente o nome, e usamos o método ObjectContainer.get(Object), que faz uma "pesquisa baseada em exemplo". A classe ObjectSet representa o resultado de uma consulta, e ObjectContainer.delete(Object) remove o objeto. Não há como ser muito mais simples que isso. O problema é que as classes com.db4o.* constituem uma API totalmente proprietária. Se você mudar, por exemplo, para o banco de dados Caché, terá que revisar todo o seu código para utilizar a API com.intersys.* deste outro SGBDOO.

 

Listagem 1. Exemplo de API de SGBDOO proprietária (db4o for Java).

public static void deleteFirstPilotByName (ObjectContainer db) {

    ObjectSet result = db.get(new Pilot("Michael Schumacher"));

    Pilot found = (Pilot)result.next();

    db.delete(found);

}

 

Mas a solução para essa questão da portabilidade veio com a norma ODMG 3.0 do Object Data Management Group[1], que normatiza o modelo de dados, a linguagem de consultas e a persistência de objetos em bancos OO, OO/relacionais e relacionais (via mapeamento). No universo Java, este padrão é incorporado pelo JDO (Java Data Objects). O JDO é mais conhecido como ferramenta ORM, portanto mais usado com SGBDs relacionais. Mas na verdade o JDO 1.0[2] (e sua linguagem de consultas, a JDOQL) é o binding[3] oficial do ODMG 3.0 para Java.

A arquitetura da JDO permite que uma implementação adequada desta API possa fazer o papel da "Interface BDOO" da Figura 2, acessando o SGBD de forma direta (dispensando JDBC ou SQL). Por outro lado, quem utilizar JDO com um SGBD relacional cairá novamente na Figura 1, com o runtime JDO se encarregando do complexo mapeamento entre objetos e tabelas, e sendo implementado sobre SQL e JDBC.

 

Figura 2. Cenário ideal de uso de SGBOO.

 

A situação seria melhor se o JDO tivesse vencido a "guerra" das APIs de persistência automática para Java, mas esta foi vencida pelo Hibernate e por outras inovações hoje presentes no Java EE 5 (como configuração via anotações). O resultado é a JPA, que tende a se tornar o novo padrão dominante (veja o tópico "A Java Persistence API"). O mundo do desenvolvimento Java é amplo o bastante para comportar diversas soluções de persistência, e o JDO sem dúvida continua tendo bom suporte e um futuro tranqüilo para quem o adotar. Mas a tecnologia está de certa forma na "segunda divisão" – ex.: todos os principais IDEs para Java já possuem ou estão preparando suporte integrado e completo à JPA, mas o suporte para o JDO é inferior (ou inexistente) e não há perspectiva que atinja o mesmo nível do oferecido para JPA.

O projeto JSR220-ORM da Fundação Eclipse começou com planos de suportar tanto a API de persistência do então futuro EJB 3.0 quanto a JDO 2.0, mas após o sucesso da JPA ficar evidente, abandonou a JDO até segundo aviso. ...

Quer ler esse conteúdo completo? Tenha acesso completo