UFG - Instituto de Informática Curso: Sistemas de Informações Arquitetura de Software Prof.: Fabrízzio A A M N Soares [email protected] Aula 6.2 – Persistência de Dados Persistência de Dados A persistência de dados, na computação, refere-se ao armazenamento não-volátil de dados, por exemplo, o armazenamento em um dispositivo físico como um disco rígido. Quando se grava um arquivo no disco, por exemplo, o dado está sendo “eternizado”, ou seja, deixa de ficar volátil na memória RAM e passa a ser escrito num dispositivo que armazena a informação de modo que ela não desapareça facilmente. Persistência de Dados Pode-se dizer que de maneira geral, o termo persistência é associado a uma ação que consiste em manter em meio físico recuperável, como banco de dados ou arquivo, de modo a garantir a permanência das informações de um determinado estado de um objeto lógico. Tipos de Persistência Arquivo Banco de Dados Persistência de Dados Na orientação a objetos, chama-se de “objetos persistentes” aqueles que permanecem existindo mesmo após o término da execução do programa. Associados à persistência estão o gerenciamento dinâmico da memória e o armazenamento de objetos em bases de dados. Persistência de Dados Somente é possível “eternizar” um objeto quando este não possui “dados dinâmicos” (runtime), ou seja, dados que só fazem sentido no contexto do tempo em que estão executando, como sockets, por exemplo. Os objetos que possuem dados de tempo de execução, se congelados, após sua recuperação os dados que não fazem mais sentido no contexto do novo tempo são ignorados ou perdidos. Persistência e mapeamento O/R Como sabemos, a tecnologia de banco de dados relacionais existe há décadas, e hoje os SGBDs são robustos e confiáveis. Os principais problemas relacionados ao armazenamento e recuperação de dados já foram solucionados, e o investimento das empresas nesses sistemas também é imenso, o que torna a sua utilização uma regra. Persistência e mapeamento O/R O uso dos bancos de dados relacionais, no entanto, traz alguns inconvenientes ao desenvolvedor em linguagens orientadas a objetos como Java. As tecnologias OO e relacional são bastante diferentes, e seu uso conjunto normalmente implica em enfatizar uma tecnologia em sacrifício da outra. Persistência e mapeamento O/R Como os bancos de dados OO ainda estão muito menos disseminados que os bancos de dados relacionais, o desafio atual dos desenvolvedores é unir dois mundos completamente distintos, utilizando a tecnologia relacional para armazenar objetos. Persistência e mapeamento O/R O armazenamento de objetos de uma aplicação é denominado persistência de objetos. Essa técnica permite que as instâncias existentes no sistema sejam armazenadas e posteriormente recuperadas, conservando-se o seu estado mesmo após a aplicação ter sido finalizada. Abordagens atuais de mapeamento Desde as suas primeiras versões, a plataforma Java oferece acesso a bancos de dados através da API JDBC, que trabalha no mesmo nível do banco, sendo o acesso às informações armazenadas feito através de comandos SQL. Abordagens atuais de mapeamento Em muitos aspectos, a JDBC é uma API de baixo nível, que muitas vezes exige do desenvolvedor o conhecimento das “nuances” do banco de dados. Apesar de ser uma maneira eficiente de acessar dados em SGBDs relacionais, e a opção que normalmente oferece melhor performance, a JDBC oferece uma abstração OO bastante limitada Trabalha-se com Tabelas, Registros e ResultSets, ao invés de Objetos). Abordagens atuais de mapeamento Para usar os recursos de bancos de dados relacionais em Java e ainda assim aproveitar os conceitos do paradigma OO, é necessário fazer o que se conhece como mapeamento Objeto-Relacional (ou simplesmente mapeamento O/R). No mapeamento O/R as classes e os atributos do sistema são mapeados para tabelas e campos/colunas, e a persistência é feita de forma transparente pela aplicação. Abordagens atuais de mapeamento Assim, objetos em memória são armazenados no banco, e objetos do banco são trazidos para a memória sempre que necessário. Com paradigmas tão diferentes, essas questões surgem durante o mapeamento: Como mapear herança? E agregação? Cada classe deve virar uma tabela? Como aproveitar os recursos do banco sem perder a abstração de objetos? Abordagens atuais de mapeamento Para suprir essas necessidades, surgiram ersos frameworks e tecnologias de persistência, a exemplo do Hibernate e do iBatis. Essas ferramentas facilitam o trabalho do desenvolvedor e aumentam sua produtividade, fornecendo poderosas APIs de manipulação de dados. Apesar de cada ferramenta possuir uma forma distinta de efetuar o mapeamento O/R, os conceitos são semelhantes e relativamente simples, baseando-se em POJOs (Plain Old Java Objects). Abordagens atuais de mapeamento O termo Plain Java Old Object (ou simplesmente, POJO) foi criado por Martin Fowler, Rebecca Parsons e Josh MacKenzie em 2000. A tradução é semelhante a “velho e bom objeto Java” e refere-se a objetos/classes Java simples, não atrelados a ferramentas ou frameworks JPA – Java Persistence API Até o J2EE 1.4 a plataforma Java não possuía uma forma simples de mapear objetos no banco de dados. A única opção era a utilização de Entity Beans, que exigem um container EJB e possuem uma complexidade razoável. Aplicações cuja arquitetura não envolvia EJBs precisavam utilizar ferramentas não padronizadas como o Hibernate para fazer a persistência, ou fazer a implementação de persistência manualmente. JPA – Java Persistence API A Java Persistence API, definida na JSR-220 (Enterprise JavaBeans,Version 3.0), padroniza o mapeamento objeto-relacional na plataforma Java. Apesar de descrita na especificação do novo EJB, a JPA não depende de um container para funcionar, sendo possível usar e testar soluções apenas com o Java SE. JPA – Java Persistence API A JPA é uma especificação baseada no conceito de POJOs, que incorpora idéias de renomados frameworks de persistência para padronizar o mapeamento O/R em Java. A API oferece uma solução completa mapeamento e persistência de objetos: para Um modo declarativo de descrever mapeamentos O/R Uma linguagem de consulta Um conjunto de ferramentas para manipular entidades JPA – Java Persistence API Em se tratando de um padrão do Java Community Process, a JPA traz ersos benefícios. O uso de um padrão para a persistência de objetos permite que ersos fabricantes trabalhem sobre os mesmos conceitos e que o desenvolvedor escolha a implementação de sua preferência. JPA – Java Persistence API A padronização vantagem: também traz outra importante pode-se alternar entre implementações de fabricantes distintos, que estejam em conformidade com a JSR-220, sem nenhum esforço adicional. Dessa forma, uma aplicação codificada de acordo com o novo padrão irá funcionar com qualquer implementação da JPA, não havendo necessidade de se conhecer (a princípio) qual tecnologia será utilizada para essa implementação. Conceitos Básicos Na JPA os objetos persistentes denominados entidades (entities). são Uma entidade é um objeto simples (POJO), que representa um conjunto de dados persistido no banco. Como entidades são definidas por classes Java comuns, sem relação com frameworks ou bibliotecas, elas podem ser abstratas ou herdar de outras classes, sem restrições. Conceitos Básicos Um conceito importante é que as entidades possuem um identificador (descrito pela chave primária) e estado, sendo seu tempo de vida independente do tempo de vida da aplicação. Assim, aplicações distintas podem compartilhar a mesma entidade, que é referenciada através de seu identificador. Conceitos Básicos Para que uma entidade se torne persistente é necessário associá-la a um persistence context (“contexto de persistência”), que fornece a conexão entre as instâncias e o banco de dados. A manipulação das entidades é feita, a partir desse contexto, por meio do entity manager (“gerenciador”), que é responsável por executar as operações básicas sobre a entidade (criação, atualização, exclusão, localização, consultas etc.). O entity manager na JPA é uma instância da interface javax.persistence.EntityManager. Conceitos Básicos A implementação da JPA é feita por um persistence provider (“provedor”). O provedor define “como as coisas funcionam”, através da implementação de todas as interfaces definidas pela especificação da JPA. Dessa forma, cada provedor decide a maneira e o momento de carregar, atualizar e armazenar as entidades, assim como sincronizar os dados com o banco. Conceitos Básicos As configurações utilizadas pelo provedor em uma determinada aplicação (conexão com o banco de dados, entidades que serão gerenciadas, tipo de transação etc.) são descritas em uma persistence unit, que é configurada num arquivo especial denominado persistence.xml. Mapeamento As classes e interfaces da JPA estão localizadas no pacote javax.persistence. A API faz uso intensivo de anotações; por isso não é necessário criar descritores XML para cada uma das entidades da aplicação. Uma entidade é uma classe Java comum, rotulada através da anotação @Entity. Mapeamento Não é necessário implementar interfaces ou estender outras classes para tornar uma classe “persistível”; A única exigência é que a classe da entidade possua um construtor sem parâmetros, pois a instanciação da classe é feita por reflexão. Mapeamento As classes e interfaces da JPA estão localizadas no pacote javax.persistence. A API faz uso intensivo de anotações por isso não é necessário criar descritores XML para cada uma das entidades da aplicação. Mapeamento Uma entidade é uma classe Java comum, rotulada através da anotação @Entity. Não é necessário implementar interfaces ou estender outras classes para tornar uma classe “persistível” a única exigência é que a classe da entidade possua um construtor sem parâmetros, pois a instanciação da classe é feita por reflexão.