Artigo SQL Magazine 15 - Mecanismos de Persistência em Java

Você precisa estar logado para dar um feedback. Clique aqui para efetuar o login
Para efetuar o download você precisa estar logado. Clique aqui para efetuar o login
Confirmar voto
0
 (0)  (0)

Artigo da Revista SQL Magazine - Edição 15.

capaSQL15.JPG

Clique aqui para ler todos os artigos desta edição

Mecanismos de Persistência em Java

por Fernando Lozano

A comunidade de desenvolvedores Java, mais do que qualquer outra, adotou as práticas de orientação a objetos no desenvolvimento de sistemas de informação. Não apenas pelo uso de componentes, como ocorre em ambientes RAD estilo Delphi e VB, mas como forma de modelar e construir as regras de negócios de uma aplicação.

Entretanto, sistemas de informação necessitam de bancos de dados, e a tecnologia mais popular nesta área ainda é a relacional. Mesmo quando são adotados bancos de dados OO (ou Objeto/Relacionais, como Oracle e PostgreSQL), o modelo de objetos do banco é bastante diferente do modelo de objetos utilizado pelo Java, ou por qualquer outra linguagem de programação. Afinal, enquanto que a linguagem lida com objetos em memória, o banco lida com objetos em disco, o que exige algoritmos e estratégias diferenciados. Dessa forma, há a necessidade de uma camada que compatibilize a visão OO dos objetos de negócios da aplicação com a visão relacional (ou OO) do banco. Daí surgem os mecanismos ou frameworks de persistência.

Este artigo apresenta inicialmente características comuns a qualquer mecanismo de persistência, depois apresenta os principais mecanismos do universo Java.

A Necessidade da Persistência de Objetos

Persistir objetos consiste em garantir que um objeto instanciado durante uma execução da aplicação tenha seu estado recuperado durante uma execução posterior de modo que ele seja o mesmo objeto.

A linguagem Smalltalk, berço das modernas práticas OO, lidava com a questão de um modo simples: todos os objetos eram persistentes. Entre uma execução e outra do ambiente Smalltalk, uma imagem do heap era salva em disco e posteriormente recuperada. É claro, isto funcionava apenas enquanto houvesse memória RAM suficiente para manter todos os objetos instanciados, coisa que não é possível para a maioria dos sistemas de informação atuais.

Estratégia similar vem sendo adotada pela prevalência de objetos, cuja implementação mais popular é o Prevayler (www.prevayler.org) (ver Nota 1). Entretanto, se você não tem memória RAM suficiente para manter todos os objetos, você precisa de um outro mecanismo de persistência, baseado no armazenamento de objetos em disco.

 

Nota 1. O Prevayler

O prevayler (www.prevayler.org), ou prevalência de objetos, é uma alternativa radical para os desenvolvedores OO mais puristas, que não desejam “poluir” suas aplicações e modelos de classes com o universo relacional. Em um mundo perfeito, seria muito mais produtivo lidar apenas com modelos de objetos e os recursos das várias classes de coleção do Java, como mapas, árvores e hashes, e não ter que carregar ou salvar dados em disco.

Ele é baseado em um mecanismo simples de snapshot (fotografia) do heap de objetos em disco, e este snapshot é atualizado periodicamente pela aplicação. Um log das operações realizadas sobre cada objeto permite a recuperabilidade em caso de falhas ou a implementação de mecanismos de distribuição (clustering).

Entretanto, o prevayler assume que todos os dados da aplicação podem ser mantidos em memória principal, e sua performance degrada-se rapidamente caso seja necessário utilizar memória virtual. Todas as afirmações “bombásticas” dos seus desenvolvedores sobre as incríveis vantagens de performance em relação a bancos de dados tradicionais devem ser pesadas em relação a este fato, de que os SGBDs são otimizados para acesso a disco, enquanto que o prevlayer é otimizado para acesso em memória. Também falta ao prevlayer a comprovação prática que os bancos relacionais já possuem em ambientes de missão crítica quanto à confiabilidade e escalabilidade.

O prevayler não utiliza um banco de dados, nem é capaz de utilizar um como meio de armazenar o shapshot dos objetos em memória, de modo que ele não faz parte do escopo deste artigo.

 

A maioria das linguagens OO fornece algum mecanismo nativo de serialização de objetos, que permite o seu envio pela rede para uma outra aplicação ou a sua gravação em um arquivo seqüencial. A serialização atende a várias aplicações, mas da mesma forma como arquivos seqüenciais não são adequados para sistemas de informação, levando ao uso de arquivos randômicos e indexados (e daí aos modernos SGBDs), a serialização também não é adequada para sistemas de informação.

Além disso, o que fazer quando a aplicação for utilizada por vários usuários simultâneos? Cada ambiente Smalltalk iria enviar, em broadcast, as modificações do estado de uma instância para que sejam aplicadas sobre os demais ambientes Smalltalk E ainda nem falamos sobre como delimitar unidades lógicas de trabalho, ou melhor, transações, e garantir sua recuperabilidade. Concorrência, consistência e integridade de dados não são coisas triviais de se obter, por isso existem os SGBDs. A função do mecanismo de persistência é nada mais do que gerenciar o salvamento e recuperação de objetos do heap da linguagem de programação para o SGBD. Entretanto, esta função também não é trivial, dadas as diferenças conceituais entre os modelos OO e Relacional.

Componentes de um mecanismo de persistência

Todo mecanismo de persistência Objeto/Relacional é formado por três componentes, a saber:

·         Uma linguagem para descrever o mapeamento de classes e atributos da aplicação para tabelas e colunas do banco de dados;

·         Uma API que permite o salvamento e recuperação de objetos do banco de dados;

·         Uma linguagem de consulta, em geral semelhante ao SQL, mas baseada em objetos e não em tabelas.

 

Mecanismos que não utilizam bancos de dados, como o Prevayler, não necessitam de uma linguagem de mapeamento (pois só existe o modelo de objetos em memória, não existe um modelo em disco para ser mapeado) nem de uma linguagem de consulta (basta percorrer o grafo de objetos). Por outro lado, mecanismos baseados em bancos não-relacionais terão componentes com finalidades semelhantes. Por exemplo, um mecanismo de persistência baseado em documentos XML teria que mapear o modelo de objetos para um XML Schema e utilizar XPath como linguagem de consulta.

 

Mapeamento OO/Relacional

Embora seja possível construir um mapeamento OO para um banco relacional pré-existente, o uso dos mecanismos de persistência é mais eficiente quando se parte de um modelo OO e daí é derivado o banco relacional.

A forma mais comum de descrever este mapeamento hoje é por meio de documentos XML, que são lidos em tempo de compilação ou em tempo de execução pelo mecanismo de persistência para gerar os comandos SQL utilizados no acesso ao banco. Como o modelo OO é mais rico do que o modelo relacional, há várias formas de se mapear um mesmo modelo de classes para tabelas, com diferentes compromissos de performance para consultas, para atualização ou flexibilidade para a evolução futura do modelo.

Por exemplo, considere o endereço de um cliente. No modelo OO, a classe Cliente teria um atributo do tipo Endereço. A classe Endereço, por sua vez, possui atributos String como nome do logradouro, bairro e cidade. Em um banco relacional, a mesma situação seria modelada como várias colunas adicionais da tabela “cliente”, gerando um modelo plano (já o modelo OO, onde Cliente contém um Endereço, é um modelo hierarquizado). Mas nada nos impede de criar uma tabela “endereço” e estabelecer um relacionamento 1:1 de endereço para cliente (ver Figura 1).

 

image002.gif
Figura 1. Diferentes formas de se mapear um modelo OO (esquerda) para um banco relacional (direita).

 

Um modelo OO pode conter atributos multivalorados (por exemplo, vários números de telefone para o mesmo cliente), enquanto que o modelo relacional exige a criação de várias colunas (telefone1, telefone2, etc) ou de uma tabela relacionada.

A herança torna a situação ainda mais complicada. Pode-se criar uma “supertabela” contendo todos os atributos possíveis para cada subclasse, ou várias tabelas representando cada nível da hierarquia de classes, com relacionamentos 1:1 entre elas.

E não podemos nos esquecer das diversas semânticas de coleções Java: listas, conjuntos e mapas. Transformar cada uma em tabelas relacionadas e preservar a semântica da coleção não é nada trivial."

A exibição deste artigo foi interrompida :(
Este post está disponível para assinantes MVP

 
Você precisa estar logado para dar um feedback. Clique aqui para efetuar o login
Receba nossas novidades
Ficou com alguma dúvida?