Você está na página 1de 6

Persistência usando Hibernate

Introdução
Hibernate é um Framewok para mapeamento Objeto/Relacional em Java
Possibilita desenvolver classes persistentes usando Java convencional:
Associação
Composição
Herança
Polimorfismo
e coleções Java
Implementa mecanismos de mapeamento:
Classes Java <-> Tabelas em SGBDs relacionais
Tipos Java <->Tipos SQL
Implementa mecanimos convenientes para consulta e recuperação de dados
Hibernate objetiva reduzir em cerca de 95% do tempo de desenvolvimento de tarefas relacionadas à persistência!

Visão Geral
A figura abaixo é uma descrição de alto nível da arquitetura do Hibernate

O Hibernate persiste objetos java comuns (POJO)


Usa reflexão para acessar as propriedades persistentes de um objeto
As classes persistentes são definidades (descritas) em documentos de mapeamento
Arquivos XML são usados para descrever os campos, associações e subclasses persistentes
Os Mapeamentos são "compilados" na inicialização da aplicação
Podem ser usados também para operações de suporte como:
Geração de esquemas do banco de dados
Geração de código-fonte Java

Código típico no uso do Hibernate:


...
SessionFactory sf = new Configuration().configure().buildSessionFactory();
Session session = sf.openSession();
Transaction tx = session.beginTransaction();
Cliente cliente = new Cliente();
cliente.setNome("Maria");
cliente.setEndereco("Endereço de Maria");
cliente.setEmail("maria@xpto.com");
session.save(cliente);
tx.commit();
session.close();
...

O código destacado está relacionado à operação do Hibernate


O primeiro passo da aplicação é obter uma Session
Esta é a principal interface entre a aplicação e o Hibernate
A SessionFactory permite a aplicação criar sessões a partir de arquivos de configuração hibernate.cfg.xml
Após definir questões transacionais (opcional) a aplicação pode usar objetos persistentes e a sessão hibernate para salvar dados
no SGBD.

Iniciando uso do Hibernate


O Hibernate funciona bem com o modelo POJO
O uso de tipos de propriedades não é restrito
É permitido qualquer tipo Java (incluindo coleções)
É possível mapear valores, coleções de valores e associações com outros objetos
A classe persistente não precisa implementar/herdar qualquer classe especial do framework

Exemplo:
import java.io.Serializable;
import java.util.Date;
public class Cliente implements Serializable {
private Long id;
private String nome;
private String endereco;
private String email;
private Date nascimento;
public Cliente(){
}

public void setId(Long id){


this.id = id;
}
public Long getId(){
return id;
}
public void setNome(String nome){
this.nome = nome;
}
public String getNome(){
return nome;
}
...
public void setNascimento(Date nascimento){
this.nascimento = nascimento;
}
public Date getNascimento(){
return nascimento;
}
}

A classe Cliente precisa de um mapeamento para se tornar persistente


<?xml version="1.0" encoding="UTF-8"?><
!DOCTYPE hibernate-mapping PUBLIC "
-//Hibernate/Hibernate Mapping DTD 2.0//EN""
http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd"><hibernate-mapping><
class
name="Cliente" table="CLIENTE"><
id column="CLIENTE_ID" name="id" type="java.lang.Long"><
generator class="sequence"/></id><property
column="NOME"
length="50"
name="nome"
not-null="true"
type="java.lang.String"
/>
...
<property
column="DATRA_NASCIMENTO"
name="nascimento"
type="java.util.Date"
/>
</class>
</hibernate-mapping>

Os documentos de mapeamento podem ser gerados automaticamente a partir da base de dados ou das classes java
O elemento <class> mapeia uma classe a uma tabela
O elemento <id> um atributo da classe à chave-primária da tabela
O elemento <property> mapeia os demais atributos do objeto às colunas da tabela
Por fim, é necesário criar o arquivo de configuração do hibernate:
<!DOCTYPE hibernate-configuration PUBLIC"
-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLMyISAMDialect</property>
<property name="hibernate.connection.driver_class">org.gjt.mm.mysql.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/exemplo</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">r00Tp@$wd</property>
<mapping-resource="Cliente.hbm.xml"/>
</session-factory>
</hibernate-configuration>

O arquivo de configuração provê informações ao framework para conectar-se ao banco de dados


O elemento <mapping-resource> aponta para o arquivo de mapeamento

Mais sobre mapeamento:


Mapeamento de Associações
Para mapear relações entre objetos persistentes usa-se os elementos <many-to-one> e <one-to-one>
Mapeamento muitos-para-um com Cliente -> Dependentes
<many-to-one name="cliente"
column="CLIENTE_ID"
class="Cliente"
not-null="true"/>

Mapeamento um-para-um com Cliente -> Usuário


<one-to-one name="usuario" class="Usuario"/>

Mapeamento de Coleções
Hibernate persiste as seguintes coleções
java.util.Map
java.util.Set
java.util.SortedMap
java.util.SortedSet
java.util.List
e qualquer Array de objetos (ou valores) persistentes
Propriedades do tipo java.util.Collection e java.util.List podem ser persistidos como "bag"
Coleções são mapeadas usando os elementos <set>, <list>, <map>, <bag>, <array> e <primitive-array>
Uma tabela para a coleção é requirida quando ela contem valores ou referencias para outras entidades mapeadas em muitos-
para-muitos
Segue um exemplo de mapeamento para uma coleção de String
<set name="enderecos" table="ENDERECOS">
<key column="CLIENTE_ID"/>
<element column="endereco" type="string"/>
</set>

O elemento <key> indica a chave estrangeira na tabela ENDERECOS


Para relacionamentos um-para-muitos as tabelas das classes são ligadas diretamente (sem uso de tableas intermediárias)
Exemplo:
<set name="dependentes" inverse="true">
<key column="CLIENTE_ID"/>
<one-to-many class="Dependente" />
</set>

Este é o mapeamento da coleção de dependentes de um Cliente


o atributo inverse indica que Dependente também referencia Cliente
<many-to-one name="cliente"
column="CLIENTE_ID"
class="Cliente"
not-null="true"
/>

Em dependente é declarada a existencia da relação.


Outras questões importantes:
Lazy Initialization
Relacionamentos ternários

Mapeamento de Herança
O Hibernate suporta três estratégias de mapeamento de herança
Uma tabela por hierarquia de classes
Uma tabela por subclasse
Uma tabela por classe concreta (polimorfismo implicito)
Não é possível misturar as estratégias para um mesmo mapeamento de classe

Suponha que tenhamos a classe Pessoa e as subclasses Cliente, Fornecedor e Funcionario


<class name="Pessoa" table="PESSOA">
<id name="id" type="long" column="PESSOA_ID">
<generator class="native"/>
</id>
<discriminator
column="TIPO_PESSOA" type="string"/>
<property name="nome" column="NOME"/>
...
<subclass
name="Cliente" discriminator-value="CLT">
...
</subclass>
<subclass
name="Funcionario" discriminator-value="FCN">
...
</subclass>
<subclass
name="Fornecedor" discriminator-value="FRC">
...
</subclass>
</class>

No código acima temos a estratégia de uma tabela por hierarquia


Apenas uma tabela é necessária, com todos os atributos da classe e suas subclasses
A coluna <discriminator> indicará qual classe uma tupla representa
A grande limitação é que colunas das subclasses não podem ser declaradas NOT-NULL
<class name="Pessoa" table="PESSOA">
<id name="id" type="long" column="PESSOA_ID">
<generator class="native"/>
</id>
<property name="nome" column="NOME"/>
...
<joined-subclass
name="Cliente" table="CLIENTE">
<key column="PESSOA_ID"/>
...
</joined-subclass>
<joined-subclass
name="Funcionario" table="FUCNIONARIO">
<key column="PESSOA_ID"/>
...
</joined-subclass>
<joined-subclass
name="Fornecedor" table="FORNECEDOR">
<key column="PESSOA_ID"/>
...
</joined-subclass>
</class>

No código acima temos a estratégia de uma tabela por subclasse


Quatro tabelas serão usadas, uma para a superclasse e três para as subclasses
As tabelas das subclasses estão ligadas à da superclasses via chave-estrangeira
Melhor estratégia do ponto de vista relacional
<class name="Cliente" table="CLIENTE">
<id name="id" type="long" column="CLIENTE_ID">
<generator class="native"/>
</id>
<property name="nome" column="NOME"/>
...
</class>
<class name="Funcionario" table="FUNCIONARIO">
<id name="id" type="long" column="FUNCIONARIO_ID">
<generator class="native"/>
</id>
<property name="nome" column="NOME"/>
...
</class>
<class name="Fornecedor" table="FORNECEDOR">
<id name="id" type="long" column="FORNECEDOR_ID">
<generator class="native"/>
</id>
<property name="nome" column="NOME"/>
...
</class>

No código acima temos a estratégia de uma tabela por classe concreta


Note que a superclasse Pessoa não foi explicitamente mencionada
Usa três tabelas, cada uma replicando os atributos de pessoa
Para indicar o polimorfismo usa-se o elemento <any>
<any name="pessoa"
meta-type="class"
id-type="long">
<column name="PESSOA_CLASS"/>
<column name="PESSOA_ID"/>
</any>

Consultas
As consultas usando Hibernate podem ser feitas de três formas
Usando HQL (Hibernate Query Language)
Usando Criteria Queries
Usando SQL Nativo

Consultas HQL

O HQL é uma linguagem SQL like, porém, "orientada a objetos"


Possibilita descrever consultas polimorficas
Possibilita consultas sobre coleções
from Pessoa pessoa where upper(pessoa.nome) like 'MARIA%'

A consulta acima retorna todos os objetos da classe pessoa e de suas subclasses que tenham o nome começado por MARIA
Possibilita descrever consultas polimorficas
Possibilita consultas sobre coleções
Query q = session.createQuery("from Pessoa pessoa where upper(pessoa.nome) like :NOME");
q.setProperties(nome);
List pessoas = q.list();

Criteria Queries
É uma API (bastante intuitiva) extendível para executar consultas
Para executá-la, basta criar um objeto Criteria e definir nele os critérios da consulta
Criteria consulta = sess.createCriteria(Pessoa.class);
consulta.add( Expression.like("nome", "Maria%") );
consulta.add( Expression.between("idade", 18, 40) );
List resultado = consulta.list();

A consulta acima vai retornar todas as Marias com idade entre 18 e 40 anos

Considerações
O Hibernate é um framework consolidado para fazer pessistência
Separa bem as coisas (o mundo OR do mundo OO)
O overhead é extremamente satisfatório
É mantido por uma comunidade muito ativa
O maior esforço para usá-lo está na construção e manutenção dos mapeamentos
Existem muitas ferramentas de apoio ao desenvolvimento usando Hibernate
XDoclets
Plugins para o Eclipse
Uso adequado destas ferramentas deixa apenas o trabalho estritamente necessário para o desenvolvedor

Recursos
Página Principal: http://www.hibernate.org
Documentação Oficial (em inglês): http://www.hibernate.org/hib_docs/reference/en/html/
Mapeamentos: http://www.j2eebrasil.com.br/jsp/tutoriais/tutorial.jsp?idTutorial=003_007
Coleções: http://www.j2eebrasil.com.br/jsp/tutoriais/tutorial.jsp?idTutorial=003_006
IDs: http://www.allapplabs.com/hibernate/hibernate_o_r_mapping_generator_element.htm
Apostila bacana: http://www.guj.com.br/content/articles/hibernate/intruducao_hibernate3_guj.pdf
POJO: http://en.wikipedia.org/wiki/Plain_Old_Java_Object

daca programa

Você também pode gostar