Você está na página 1de 9

Persistencia em java

 A persistência é definida como a capacidade que uma linguagem ou ambiente de


programação tem de permitir que os dados e objetos “sobrevivam” a execução de um
processo, para mais tarde utilizá-los em outro processo. Atualmente o conceito inclui
também algumas operações que podem ser realizadas sobre os dados persistentes, tais
como ordenação, pesquisa e gerenciamento de concorrência/integridade.
Serialização
Consiste na transformação de objetos em memória em uma seqüência de bytes
que pode ser salva e posteriormente recuperada, podendo ser considerada uma
forma de persistência simples.
Durante a serialização de um objeto, todos os objetos alcançáveis a partir dele
também são serializados, a fim de manter consistente todo o seu estado. Como
exemplo:
Nela temos um objeto A, que aponta para 4 objetos (B,C,D,E), que por
sua vez apontam para outros dois objetos (F,G). Em uma serialização de A,
todos esses objetos (B,C,D,E,F,G) seriam incluídos na seqüência de bytes.
Os bytes serializados podem ser armazenados em um arquivo ou SGBD e
posteriormente recuperados. O processo de leitura restaura na memória as
estruturas dos objetos originais, mas não suas identidades, o que, dependendo
da aplicação, pode causar problemas. Os objetos quando reconstruídos contém
os mesmos dados, mas podem ocupar posições distintas de memória -
implicando, por exemplo, em hashcodes diferentes.

As funcionalidades de serialização estão disponíveis no pacote java.io. As


classes candidatas a serialização têm que obrigatoriamente implementar a
interface Serializable. Essa interface não possui métodos ou atributos e é
utilizada como um marcador.

Para serializar um objeto é necessário passá-lo como parâmetro para o


método writeObject da classe ObjectOutputStream. Para recuperá-lo deve-se utilizar
o método readObject da classe ObjectInputStream. As streams de serialização
possuem todo o mecanismo para obter e ajustar o estado dos objetos e
percorrer e reconstruir o conjunto de objetos alcançáveis. Elas devem ser
utilizadas em conjunto com outras streams que façam a ligação com um
dispositivo de sistema, como arquivos, sockets ou pipes, ou juntamente com
um buffer para armazenar a seqüência de bytes gerada.

É muito fácil utilizar a serialização. No exemplo a seguir abrimos um arquivo,


associamos uma stream de saída e persistimos um objeto da classe Date

Para recuperar o objeto basta fazer a operação inversa - ler o arquivo e


associar uma stream de entrada:

Em aplicações com pequeno volume de dados e operações a serialização é


um excelente recurso. No entanto, em aplicações comerciais seu uso é
praticamente inviável; objetos que podem ser acessados por mais de um
caminho são armazenados de forma única em uma serialização, mas de
forma redundante se forem serializações diferentes, sem qualquer controle
de consistência. Guardar todos os objetos da aplicação a partir de um objeto
de coleção, para evitar a redundância, acarreta em um imenso impacto de
desempenho, visto que somente é possível serializar ou recuperar todos os
objetos de uma vez. Além disso, não há como fazer consultas ou permitir
acesso concorrente aos objetos persistentes.

Java Database Connectivity

Com a API JDBC (Java Database Connectivity), desenvolver aplicações cliente-


servidoras de banco de dados se tornou um processo mais simples, devido à
maior independência de SGBDs provida pela API.

Essa independência é atingida através dos drivers JDBC. Cada fornecedor que
deseja tornar seu SGBD acessível a partir de uma aplicação Java disponibiliza
um driver JDBC. Este driver faz toda a comunicação com o banco,
encapsulando quaisquer características particulares que o fabricante tenha
implementado. Em alguns casos, pode ser necessário inclusive que o driver
implemente funcionalidades não disponíveis no SGBD.
 ANOTAÇÕES

 FAVORITAR

 CONCLUÍDO

 GOSTEI

Suporte ao alunoAnotarMarcar como concluído


ArtigosBanco de DadosArtigo SQL Magazine 6 - Métodos de persistência em Java

A persistência é definida como a capacidade que uma linguagem ou ambiente de


programação tem de permitir que os dados e objetos “sobrevivam” a execução de um
processo, para mais tarde utilizá-los em outro processo. Atualmente o conceito inclui
também algumas operações que podem ser realizadas sobre os dados persistentes, tais
como ordenação, pesquisa e gerenciamento de concorrência/integridade.

Neste artigo apresentaremos as opções básicas para persistência de objetos Java:


serialização, conexões JDBC, ferramentas de mapeamento e uso de Entity Beans.

Serialização
Consiste na transformação de objetos em memória em uma seqüência de bytes que pode
ser salva e posteriormente recuperada, podendo ser considerada uma forma de
persistência simples.

Durante a serialização de um objeto, todos os objetos alcançáveis a partir dele também


são serializados, a fim de manter consistente todo o seu estado. Como exemplo, veja
a figura 1: nela temos um objeto A, que aponta para 4 objetos (B,C,D,E), que por sua
vez apontam para outros dois objetos (F,G). Em uma serialização de A, todos esses
objetos (B,C,D,E,F,G) seriam incluídos na seqüência de bytes.

Os bytes serializados podem ser armazenados em um arquivo ou SGBD e


posteriormente recuperados. O processo de leitura restaura na memória as estruturas dos
objetos originais, mas não suas identidades, o que, dependendo da aplicação, pode
causar problemas. Os objetos quando reconstruídos contém os mesmos dados, mas
podem ocupar posições distintas de memória - implicando, por exemplo, em hashcodes
diferentes.
Fi
gura 1. Serialização de um objeto.

As funcionalidades de serialização estão disponíveis no pacote java.io. As classes


candidatas a serialização têm que obrigatoriamente implementar a interface Serializable.
Essa interface não possui métodos ou atributos e é utilizada como um marcador.

Para serializar um objeto é necessário passá-lo como parâmetro para o


método writeObject da classe ObjectOutputStream. Para recuperá-lo deve-se utilizar o
método readObject da classe ObjectInputStream. As streams de serialização possuem todo o
mecanismo para obter e ajustar o estado dos objetos e percorrer e reconstruir o conjunto
de objetos alcançáveis. Elas devem ser utilizadas em conjunto com outras streams que
façam a ligação com um dispositivo de sistema, como arquivos, sockets ou pipes, ou
juntamente com um buffer para armazenar a seqüência de bytes gerada.

É muito fácil utilizar a serialização. No exemplo a seguir abrimos um arquivo,


associamos uma stream de saída e persistimos um objeto da classe Date

FileOutputStream arquivo = new FileOutputStream("DataHora");


ObjectOutputStream sequencia = new ObjectOutputStream(arquivo);
sequencia.writeObject(new Date());
sequencia.flush();

Para recuperar o objeto basta fazer a operação inversa - ler o arquivo e associar uma
stream de entrada:

FileInputStream entrada = new FileInputStream("DataHora");


ObjectInputStream sequencia = new ObjectInputStream(entrada);
Date data = (Date) sequencia.readObject();

Em aplicações com pequeno volume de dados e operações a serialização é um excelente


recurso. No entanto, em aplicações comerciais seu uso é praticamente inviável; objetos
que podem ser acessados por mais de um caminho são armazenados de forma única em
uma serialização, mas de forma redundante se forem serializações diferentes, sem
qualquer controle de consistência. Guardar todos os objetos da aplicação a partir de um
objeto de coleção, para evitar a redundância, acarreta em um imenso impacto de
desempenho, visto que somente é possível serializar ou recuperar todos os objetos de
uma vez. Além disso, não há como fazer consultas ou permitir acesso concorrente aos
objetos persistentes.
Java Database Connectivity
Com a API JDBC (Java Database Connectivity), desenvolver aplicações cliente-servidoras
de banco de dados se tornou um processo mais simples, devido à maior independência
de SGBDs provida pela API.

Essa independência é atingida através dos drivers JDBC. Cada fornecedor que deseja
tornar seu SGBD acessível a partir de uma aplicação Java disponibiliza um driver
JDBC. Este driver faz toda a comunicação com o banco, encapsulando quaisquer
características particulares que o fabricante tenha implementado. Em alguns casos, pode
ser necessário inclusive que o driver implemente funcionalidades não disponíveis no
SGBD.

A JDBC se encontra nos pacotes java.sql, onde está o cerne da API, e javax.sql. Entre as
classes e interfaces mais importantes podemos citar (figura 2): i) classe DriverManager,
que gerencia o acesso a múltiplas fontes de dados; ii) interface Driver, que representa
um driver JDBC; iii) interface Connection, que representa uma conexão com a fonte de
dados; iv) interfaces Statement, PreparedStatement e CallableStatement que permitem a
execução de comandos SQL e stored procedures; v) interface ResultSet que representa
os dados obtidos do banco; vi) classe Types que define os tipos de dados JDBC; vii)
interface DatabaseMetaData que obtém informações sobre as capacidades do banco que
são disponibilizadas pelo driver em uso.

A JDBC é baseada nos padrões X/Open SQL CLI, SQL92 e SQL99 e tem seu
foco em acesso a dados relacionais. Entretanto, a especificação não restringe
seu uso, sendo possível implementar drivers que acessem outros tipos de
fontes de dados, tais como bancos de dados objeto-relacionais (BDORs),
bancos de dados orientados a objetos (BDOOs), XML etc.

A forma mais simples de persistir objetos com JDBC é embutir chamadas


SQL diretamente nas classes de negócio da aplicação. Essa abordagem, no
entanto, diminui a reusabilidade das classes, já que elas se tornam
dependentes do mecanismo de persistência utilizado. Por exemplo, se
decidirmos substituir o uso de um banco de dados relacional por um banco de
dados XML, teremos que alterar as chamadas JDBC em toda a aplicação.
Uma forma de minimizar esse problema é criar classes para encapsular a
comunicação com o banco de dados, formando uma “camada de persistência”.
A desvantagem nesse caso é que o desenvolvedor terá que perder muito tempo
na implementação dessas novas classes, se desviando do negócio principal da
aplicação.

Mapeamento Objeto-Relacional

Com um mecanismo de mapeamento objeto-relacional (MMOR) o


desenvolvedor não precisa se preocupar com chamadas JDBC ou SQL; ele
apenas configura em arquivos de metadados como as classes de negócio
deverão ser armazenadas no banco (qual campo vai armazenar qual atributo
etc.) e o mecanismo de mapeamento cuida do resto. Na maioria dos MMORs
esses arquivos seguem o padrão XML.

Alguns MMORs disponibilizam ferramentas que, a partir do modelo de


classes da aplicação, geram automaticamente o esquema para o SGBD e os
metadados de mapeamento. Em alguns casos também é gerado código fonte
com o esqueleto das classes, onde a lógica de negócio pode ser inserida (ou
codificada em subclasses). Também é comum encontrar MMORs que
oferecem atualização automática de objetos persistentes modificados e carga
de dados sob demanda (lazy loading).

O tipo de MMOR mais simples é o que disponibiliza classes de persistência.


Uma classe de persistência recebe um objeto (através de métodos) e cuida de
armazená-lo/recuperá-lo do banco de dados. Ela faz a leitura, em tempo de
execução, dos arquivos de metadados para identificar como o objeto deve ser
salvo/lido do banco. Veja um exemplo de uso de classe de persistência
na listagem 1.

Outro tipo de MMOR são os pós-processadores de código. O pós-


processamento adiciona às próprias classes de negócio a funcionalidade de
persistência, de forma transparente para o desenvolvedor.

A principal vantagem dos MMORs é o acesso a dados legados em SGBDRs.


Novas aplicações podem ser desenvolvidas e executadas de forma
concomitante a aplicações legadas, permitindo a migração suave de tecnologia
ou a criação de novos serviços.

A desvantagem é que em aplicações com modelos complexos os MMORs


tendem a apresentar desempenho insatisfatório. Outras deficiências comuns
são a ausência de ferramentas para evolução do modelo da aplicação e
mecanismos de consulta ad hoc pouco integrados à linguagem de
programação OO.

Entity Beans

A especificação J2EE (Java 2 Platform Enterprise Edition) define um padrão


de arquitetura para o desenvolvimento e ambiente de execução de aplicações,
tratando questões como disponibilidade, escalabilidade, concorrência e
segurança de forma transparente. Estes ambientes de execução, chamados
containers, provêem serviços e abrigam componentes de aplicação.

Segundo a especificação J2EE dois tipos de containers estão previstos:


containers web, que abrigam servlets e páginas JSP em um servidor HTTP; e
containers EJB (Enterprise JavaBeans) que abrigam componentes de negócio.

Os Enterprise JavaBeans são um modelo de desenvolvimento de componentes


distribuídos, utilizados em aplicações multicamadas - os EJBs permanecem na
camada de lógica do negócio, ou segunda camada.

Um componente EJB é encapsulado por um container EJB (figura 3). Esse


modelo reduz o trabalho do desenvolvedor, pois o container controla o ciclo
de vida e execução do componente, gerenciando automaticamente processos
de persistência, connection pooling, transações, conexão remota com a
interface cliente (thin client), segurança, concorrência e distribuição.

A especificação EJB 2.0 prevê três tipos de componentes:

 Session bean: Representa uma ação, serviço ou tarefa da aplicação,


como aluguel de livro ou venda de assinatura. Geralmente interage com
Entity Beans.
 Entity Beans Representa uma entidade do negócio e possui a
persistência como característica inerente – como exemplo de entity
beans temos Cliente ou Livro. Normalmente são manipulados por
session beans.
 Message-driven beans: Assim como os session beans, implementam
processos que podem envolver outros componentes. A diferença é que
são chamados por mensagens e suas execuções são assíncronas às
chamadas.

A persistência de um entity bean pode ser de dois tipos:


 Bean-managed persistence (BMP): O desenvolvedor implementa o
código para armazenamento e recuperação de dados. O mais comum é a
utilização da API JDBC para acessar SGBDs.
 Container-managed persistence (CMP): O container é responsável
pela implementação da persistência. Nesse caso, o fornecedor do
container disponibiliza uma ferramenta para a configuração do
mapeamento (qual campo recebe qual atributo, qual tabela representa
uma classe etc.). Disponibiliza a EJB-QL (EJB Query Language), uma
linguagem de consulta padrão.

Um dos atrativos de um entity bean é que o desenvolvedor não fica


responsável por gerenciar quando a leitura/escrita deve ser feita na base de
dados – essa tarefa é de responsabilidade do container EJB. Se for utilizado
CMP, o desenvolvedor também fica livre da implementação da persistência.
No entanto, por ser mais declarativo que procedural, é perceptível um certo
desconforto nos desenvolvedores ao trabalhar com CMP sem passar pela
experiência de criar entity beans BMP e entender o que está acontecendo “por
debaixo dos panos”.

Outro cenário para implementação de persistência em componentes EJB é o


uso de session beans com acesso direto a uma base de dados, através de JDBC
ou outro mecanismo de ligação com SGBDs. Nesse caso o desenvolvedor fica
responsável por implementar e definir quando a persistência será realizada.

A arquitetura EJB exige um modelo de desenvolvimento diferenciado, por


muitas vezes guiado por padrões de projeto (design patterns) e que requer um
aprendizado demorado por parte do desenvolvedor. Um modelo de objetos
que tenha sido previamente especificado para uma aplicação deve ser
adequado à arquitetura EJB, para que possa extrair maior desempenho desta
plataforma. Ainda, a manutenção de componentes pode ser custosa devido à
quantidade de trechos de código (classe do componente, interfaces remota e
local, interfaces home) que podem passar por mudanças.

Apesar de todo o investimento que vem sendo feito, nem sempre a aplicação
de EJBs é adequada e a escolha dessa arquitetura deve ser feita de forma
criteriosa.

O que é framework de persistência?


Frameworks de persistência são utilizados para realizar o mapeamento de
dados de aplicações desenvolvidas no paradigma orientado a objetos para
permitir seu armazenamento em bancos de dados relacionais e por isto são
também denominados frameworks de mapeamento objeto-relacional.

Você também pode gostar