HIBERNATE COMO CAMADA DE PERSISTÊNCIA Geraldo Leite Brito de Moraes Rua Minervino S. Fontes, nº 161, Bairro Salgado Filho, Aracaju - SE [email protected] ABSTRACT To develop a system, normally one becomes necessary to store the data in a database, and this in turn generally follows the relational model. Diverse technologies that they look to facilitate to the development using relational databases and oriented object programming languages exist guided the object through the creation of classes that occult the access to the data. Knowing some of these technologies it can be reduced the time and the complexity of development of the systems without that it has loss of performance when executing it. The objective of this article is to show a model of persistence of data for the Java platform. Na figura 1 podemos notar que o Hibernate serve de intermediário entre os objetos e o banco de dados. Termos Gerais Gerenciamento, Desempenho, Desenvolvimento, Padronização, Reaproveitamento. Teoria, Palavras-Chave Hibernate, Java, Persistência, Banco de Dados Relacional. Figura 1. Arquitetura do Hibernate [1] 1. RESUMO 3. MAPEANDO COM O HIBERNATE Para desenvolver um sistema, normalmente faz-se necessário armazenar os dados em um banco de dados, e este por sua vez geralmente segue o modelo relacional. Existem diversas tecnologias que procuram facilitar o desenvolvimento utilizando bancos de dados relacionais e linguagens de programação orientadas a objeto através da criação de classes que ocultam o acesso aos dados. Conhecendo-se alguma dessas tecnologias pode-se reduzir o tempo e a complexidade de desenvolvimento dos sistemas sem que haja perda de desempenho ao executá-lo. O objetivo deste artigo é mostrar um modelo de persistência de dados para a plataforma Java. Para construir uma aplicação WEB, em Java, utilizando o Hibernate como camada de persistência será necessário ter um Web Container J2EE, como o Tomcat, e um datasource configurado, além das bibliotecas do Hibernate. As suas configurações ficam armazenadas em um arquivo hibernate.cfg.xml para as configurações genéricas, como podemos ver na listagem 1. 2. INTRODUÇÃO As linguagens de programação orientadas a objeto facilitam bastante o desenvolvimento de aplicações, mas a necessidade de realizar operações com banco de dados relacionais dificulta o desenvolvimento de um sistema e torna-o complexo, já que a linguagem é orientada a objetos e o banco de dados não. Para resolver esse problema existem tecnologias que permitem ocultar o acesso a tabelas do modelo relacional em objetos e automaticamente gerenciar sua persistência. O Hibernate é um framework para modelagem objeto/relacional na plataforma Java, composta por um conjunto de pacotes de classes Java que permite o mapeamento de tabelas através de objetos que podem ser usados na recuperação e atualização dos dados, além de possuir um serviço de consulta nos objetos. [1] <?xml version='1.0' encoding='utf-8'?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN" "http://hibernate.sourceforge.net/hibernateconfiguration-2.0.dtd"> <hibernate-configuration> <session-factory> <property name="connection.datasource"> java:comp/env/jdbc/sgp</property> <property name="show_sql">true</property> <property name="dialect"> net.sf.hibernate.dialect.PostgreSQLDialect </property> <!-- Mapping files --> <mapping resource="hibernate/Estado.hbm.xml"/> <mapping resource="hibernate/Cliente.hbm.xml"/> </session-factory> </hibernate-configuration> Listagem 1. Arquivo hibernate.cfg.xml Podemos perceber que no arquivo hibernate.cfg.xml a propriedade connection.datasource define qual será a fonte de dados utilizada, enquanto a propriedade dialect define qual a classe será utilizada como dialeto para construção dos comandos SQL que serão submetidos ao banco de dados. Existe também a chamada de cada arquivo específico que irá definir o mapeamento entre um objeto e uma dada tabela. [3] Deve existir um arquivo XML para o mapeamento de cada objeto, como o que pode ser visto na listagem 2. <?xml version='1.0' encoding='utf-8'?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN" "http://hibernate.sourceforge.net/hibernatemapping-2.0.dtd"> <hibernate-mapping> <class name="teste.Estado" table="Estado"> <id name="sigla" type="string" unsavedvalue="null"> <generator class="assigned"/> </id> <property name="descricao"/> </class> </hibernate-mapping> package teste; import java.io.Serializable; public class Cliente implements Serializable { private long cod; private String nome; private String telefone; private Estado estado; public long getCod() { return cod; } public void setCod(long cod) { this.cod = cod; } . . . } Listagem 4. Exemplo de Java Bean 4. UTILIZANDO O HIBERNATE Para criar uma sessão no Hibernate é necessário possuir uma instância da classe SessionFactory e após sua utilização ela deve ser liberada através da chamada ao método close. A listagem 5 mostra como uma sessão do Hibernate pode ser criada. Listagem 2. Arquivo XML mapeando uma tabela package teste; Um arquivo XML específico de mapeamento associa um Java Bean a uma tabela do banco de dados onde cada instância da classe (objeto) corresponde a um registro e cada propriedade ao valor de um campo na tabela. O Hibernate possui um conjunto de classes as quais implementam a interface IdentifierGenerator e que servem para indicar de que forma as chaves primárias serão geradas. A forma que uma propriedade é mapeada indica se ela é uma propriedade simples ou se ela indica um relacionamento com outro objeto (tabela) e como é a natureza desse relacionamento, assim como é apresentado na listagem 3. <?xml version='1.0' encoding='utf-8'?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN" "http://hibernate.sourceforge.net/hibernatemapping-2.0.dtd"> <hibernate-mapping> <class name="teste.Cliente" table="Cliente"> <id name="cod" type="long" unsaved-value="0"> <generator class="increment"/> </id> <property name="nome"/> <property name="telefone"/> <many-to-one name="estado"/> /class> </hibernate-mapping> Listagem 3. Arquivo XML mapeando uma tabela Os Java Beans que são mapeados em tabelas, devem implementar a interface Serializable para que possam ser persistidos pela JVM (Java Virtual Machine) e ter todos os métodos sets e gets com visibilidade pública, podendo ser reutilizados no projeto como bean no JSP de interface ou na lógica, pois não possuem nenhum código específico do Hibernate. Podem existir propriedades que não foram mapeadas com a tabela, mas não deve existir nenhum tipo de regra de negócio. Na listagem 4 podemos ver um exemplo de Java Bean que pode ser mapeado utilizando o Hibernate. public class HibernateUtil { private static final SessionFactory sessionFactory; static { try {sessionFactory = new Configuration().configure() .buildSessionFactory(); } catch (Throwable ex) {} } public static Session openSession() throws HibernateException { return sessionFactory.openSession(); } } Listagem 5. Criando uma sessão no Hibernate Pode-se recuperar um objeto através do método load ou executando o método refresh tendo sido definidas as propriedades que são identificadores (chaves primárias). Session hbSession = HibernateUtil.openSession(); Cliente obj = null; obj = (Cliente) hbSession.load(Cliente.class, new Long(1)); hbSession.close(); Session hbSession = HibernateUtil.openSession(); Cliente obj = new Cliente(); obj.setCod(1); hbSession.refresh(obj); hbSession.close(); Listagem 6. Carregando um objeto com o Hibernate Para atualizar um objeto podem ser utilizados os métodos save ou update. O Hibernate conta com a classe Transaction que gerencia o controle de transações com o banco de dados, permitindo que em caso de erro todas as operações sejam desfeitas. Session hbSession = HibernateUtil.openSession(); Transaction tx= hbSession.beginTransaction(); try { Cliente obj = new Cliente(); obj.setCod(1); obj.setNome(“José dos Santos”); hbSession.save(obj); ou hbSession.update(obj); tx.commit(); } catch { tx.rollback(); } hbSession.close(); Listagem 7. Salvando um objeto com o Hibernate O Hibernate conta ainda com as classes Query e Criteria para efetuar consultas nos objetos, podendo-se passar parâmetros através da linguagem HQL (Hibernate Query Language) que é similar à linguagem SQL[1]. Query qry = hbSession.createQuery("from Cliente as cliente where cliente.codigo = ?"); qry.setLong(0,cliente.getCod()); List clientes = qry.list(); List cats = sess.createCriteria(Cat.class) .add(Expression.like("name", "Fritz%")) .add(Expression.or( Expression.eq("age", new Integer(0)), Expression.isNull("age") )).list(); Listagem 8. Consultando objetos com o Hibernate 5. CARACTERÍSTICAS O Hibernate possui algumas características singulares em relação a outras tecnologias equivalentes na plataforma Java. Entre ela podemos citar: - Os Java Beans que mapeiam as tabelas não precisam importar nenhuma interface e nem estender nenhuma classe do pacote Hibernate, permitindo que elas possam ser facilmente reaproveitadas e utilizadas na interface e ao longo do projeto. - As classes do Hibernate mantém o sincronismo entre os objetos de memória e os dados no banco de dados permitindo que seja feito um acesso simultâneo à base por aplicações legadas. - Existem produtos de terceiros como o Middlegen [2] e o TableGen [4] que extraem os dados de um banco de dados e criam os arquivos XML de mapeamento para o Hibernate automaticamente, facilitando o trabalho para o desenvolvedor e ainda assim permitindo futuros ajustes nos arquivos caso haja necessidade. - O desenvolvedor pode, na codificação, explicitar um insert ou update no banco de dados através dos métodos save e update, como pode permitir que o Hibernate decida o comando adequado através da chamada ao método saveOrUpdate. - Existe uma classe Query que implementa a consulta sobre os objetos mapeados permitindo que o desenvolvedor se abstraia completamente do modelo relacional. - Não impede o acesso direto ao banco de dados numa necessidade excepcional, inclusive disponibilizando na classe Session um método para obter a conexão JDBC com o banco de dados. - Existe uma classe para gerenciamento de transações, facilitando em muito a manutenção de tarefas que precisam ser executadas em conjunto. - A existência de um arquivo que define o dialeto a ser utilizado permite a mudança do banco de dados utilizado sem que seja necessário alterar a codificação do sistema. 6. ANÁLISE FINAL A utilização de uma tecnologia que dê ao desenvolvedor a visão do armazenamento através de objetos pode facilitar consideravelmente o desenvolvimento de um sistema além de permitir futuras alterações como a mudança do fabricante do banco de dados sem necessitar alterações na codificação. Em algumas situações específicas pode ser necessário o acesso direto ao banco de dados para executar consultas complexas e utilizar funções especiais disponibilizadas em sua API, por isso é muito importante que se possa interagir diretamente com o mesmo. Apesar da implementação das tecnologias de mapeamento do modelo relacional terem evoluído bastante, ainda há casos onde a interação para mapear cada registro de uma consulta em objetos pode degradar bastante o desempenho se comparado ao acesso direto usando JDBC. Por tudo isso o mais indicado é o uso de uma tecnologia híbrida onde o armazenamento e recuperação em formulários de cadastros se dê por objetos e as consultas por ferramentas especializadas em gerar relatórios. Para o desenvolvedor que esteja utilizando a linguagem Java, o Hibernate atende de forma simples e eficaz a sua proposta de mapeamento das tabelas através de objetos, e ainda permite que outras API’s compartilhem com ele o acesso simultâneo e direto aos dados. 7. REFERÊNCIAS [1] Hibernate - Extraído em 20/09/2004: http://www.hibernate.org [2] Middlegen. Extraído em 20/09/2004: http://boss.bekk.no/boss/middlegen/plugins/hibernate.html [3] Get started with hibernate - Extraído em 20/09/2004: http://www.javaworld.com/javaworld/jw-10-2004/jw-1018hibernate.html [4] TableGen Main Page – Extraído em 20/09/2004: http://freespace.virgin.net/joe.carter/TableGen/index.html 8. BIBLIOGRAFIA GUJ | Grupo de Usuários Java: Sua Comunidade Virtual Java - Livre-se do SQL: uma introdução ao Hibernate - Extraído em 10/10/2004: http://www.guj.com.br/java.artigo.125.1.guj Livro: Hibernate in Action ISBN: 193239415X Editora: Manning Autor: Christian Bauer and Gavin King Ano: 2004 Livro: Hibernate: A Developer’s Notebook ISBN: 0-596-00696-9 Editora: Manning Autor: James Elliott Ano: 2004