Hibernate
Java avançado – PCC
Jobson Ronan {jrjs@cin.ufpe.br}
Guilherme Kelly {gkmo@cin.ufpe.br}
O que é?
Hibernate é uma moderna solução de
mapeamento objeto-realcional(ORM)
Persistência tranparente (POJO/Java
Beans)
“Lazy Fetching”
Uso de uma Cache
Três estratégias para o mapeamento de
heranças
O que é?
Pra que transparência?
Persistência sem impacto no código dos
objetos de negócio
Qualquer classe pode ser uma classe
persistente sem ser necessário
implementar nenhuma classe ou interface
Classes persistentes podem ser usadas
fora do contexto de persistência (ex
Testes)
Total portabilidade sem dependências
Problemas dos BDRs
Modelagem
Não há polimorfismo
Não há herança
Lógica de negócio
Stored procedures -> perca de
portabilidade
Vantagens dos RDBs
Trabalhar com grandes quantidades de
dados
Busca, ordenação
Trabalhar com conjuntos de dados
Junções e agregações
Compartilhamento
Concorrência (Transações)
Muitas aplicações
Integridade
Restrições (Constraints)
Isolação de transações
Obviamente, ainda precisamos dos
RDBs
Objetivo
Aproveitar-se das vantagens
oferecidas pelos RDBs
Isso sem perder a orientação a
objetos
Objetivo Real
Ter menos trabalho
Ter um DBA feliz
Em prática
Locadora em partes...
Em prática
Classe Persistente package br.org.citi.pec.locadora;
public class Filme {
Construtor default private int codigo;
private String nome;
Pares de Get´s e
Set´s public int getCodigo() {
return codigo;
Uma propriedade
}
identificadora private void setCodigo(int codigo) {
this.codigo = codigo;
}
public String getNome() {
return nome;
}
private void setNome(int nome) {
this.nome = nome;
}
}
Em prática
Mapeamento XML
Metadado legível
Mapeamento de tabelas e colunas
Em prática
Salvando um objeto
Session session = sessionFactory.openSession();
Transaction tx = s.beginTransaction();
Filme filme = new Filme();
filme.setNome(novoNome);
session.save(filme);
tx.commit();
session.close();
Também pode ser usado saveOrUpdate
Em prática
Carregando um objeto
Session session = sessionFactory.openSession();
Filme filme = (Filme) session.load(Filme.class,
new Integer(filmeId);
session.close();
Não use load para determinar se um objeto
existe (uma exceção é lançada neste caso)
Use get. Este retorna null caso o objeto não
exista
Em prática
Removendo um objeto
Session session = sessionFactory.openSession();
Transaction tx = s.beginTransaction();
Filme filme = (Filme) session.get(Filme.class,
new Integer(filmeId);
session.delete(filme);
tx.commit();
session.close();
Em prática
Atualizando um objeto (Dirty Checking)
Obetendo um filme e alterando seu nome
Session session = sessionFactory.openSession();
Transaction tx = s.beginTransaction();
Filme filme = (Filme) session.get(Filme.class,
new Integer(filmeId);
filme.setNome(novoNome);
tx.commit();
session.close();
Não é necessário uma chamada explicita do update
Estado dos Objetos
Alguns conceitos sobre objetos
Transiente.
• Nunca persistido. Não associado a nenhuma
sessão (Session)
Persistente
• Associado a uma única sessão
Desacoplado (Detached)
• Já persistido, mas não associado a nenhuma
sessão
Estado dos Objetos
Dirty Checking só funciona em
objetos persistentes
Use update para objetos desacoplados
Mais prática
Melhorando nosso modelo...
Mais prática
Classes persistentes
package br.org.citi.pec.locadora;
public class Cliente {
private String login;
private String CPF;
private String nome;
private Set locacoes = new Hashset();
//... Get´s e Set´s
}
Mais prática
Classes persistentes
package br.org.citi.pec.locadora;
public class Locacao {
private int id;
private Filme filme;
private Cliente cliente;
private Date dataLocacao;
private Date datadevolucao;
//... Get´s e Set´s
}
Mais prática
XML...
Mais prática
XML...
Mais prática
Persistência transitiva
Locacao locacao = new Locacao();
Locacao.setDataLocacao(new Date());
Session session = sessionFactory.openSession();
Transaction tx = s.beginTransaction();
Filme filme = (Filme)
session.get(Filme.class, new Integer(filmeId);
Cliente cliente = (Cliente)
session.get(Cliente.class, login);
locacao.setCliente(cliente);
locacao.setFilme(filme);
cliente.getLocacoes().add(locacao);
tx.commit();
session.close();
Otimizando
Como as coleções são carregadas
Lazy fetching (Default)
Eager (Outer Join) fetching
• Indicado nos XML, ou na própria consulta
Lazy fetching
SQL escondido:
Cliente cliente = (Cliente) session.get(Cliente.class, login);
SELECT … FROM CLIENTES C WHERE C.LOGIN = ?
Iterator cliente = cliente.getLocacoes().iterate();
SELECT … FROM LOCACOES L WHERE L.LOGIN_CLIENTE = ?
Filme filme = locacao.getFilme();
SELECT … FROM FILMES F WHERE F.FILME_ID = ?
Outer join fetching
SQL escondido:
Cliente cliente = (Cliente) session.get(Cliente.class, login);
SELECT … FROM CLIENTES C
LEFT OUTER JOIN LOCACOES L ON L.LOGIN_CLIENTE = C.LOGIN
LEFT OUTER JOIN FILME F ON L.FILME_ID = F.FILME_ID
WHERE C.LOGIN = ?
Herança
Estratégias para o mapeamento de
herança
Uma tabela por hierarquia de classes
Uma tabela por subclasse
Uma tabela por classe concreta
Herança
Uma tabela por subclasse
...
...
Otimizando
Como otimizar?
Minimizando a leitura de linhas das
tabelas
Minimizando a quantidade de comandos
SQLs enviados
Otimizando
Minimizando a leitura de linhas das
tabelas
Usar lazy fecthing
Minimizando a quantidade de
comandos SQLs enviados
Usar outer join fetching
Otimizando
Problemas
Usar lazy fecthing
• Problema dos n+1 selects (muitos selects!)
Usar outer join fetching
• Problema do produto cartesiano (grandes
conjuntos de dados)
Otimizando
Solucionando problemas de
otimização
Stratégia de Fecthing definida em
tempo de execução
Batch Fecthing
Utilizar um cache de segundo nível
Consultas
HIbernate Query Lanuage
Permite que se expresse quase tudo o
que se precisa expressar em SQL,
porém mais orientado a objetos
Três maneiras de se fazer consultas
no Hibernate
HQL
Criteria
SQL nativo
HQL
Tornar SQL orientado a objetos
Classes e propriedades ao invés de Tabelas e colunas
Polimorfismo
Associações
Total suporte a operações relacionais
Joins
Projeções
Funções agregadas e agrupamento
Ordenação
SubQueries
Chamadas a funções SQL
HQL
A consulta mais simples possivel HQL
from Filme
Devolva todos os filmes
List filmes = session.createQuery(“from Filme”).list();
As consultas podem ser paginadas
Query query = session.createQuery(“from Filme”);
query.setFirstResult(20);
query.setMaxResults(30);
List filmes = query.list();
HQL
Uma consulta com ordenação
from Locacao l order by l.dataLocacao desc
Caso esteja interessado em um único
resultado
Query query = session.createQuery(
“from Locacao l order by l.dataLocacao desc”);
Locacao locacao = query.uniqueResult();
HQL
Uma consulta com joins
select c from Cliente c left join [fetch] c.locacaoes l
where l.dataLocacao > 3/5/2005
Todos os clientes com suas locações efetuadas após o dia
3
Definição da estratégia de fetching
Com o fetch: Coleções já inicializadas
Sem o fetch: lazy collections
HQL
HQL suporta os mesmos operadores que SQL
Operadores do HQL:
Comparação: =, , , >=,
Modelagem OO
“Mais classes que tabelas”
Classse Endereco
• Propriedade: rua, numero, bairro...
Rua, numero, bairro,... Colunas da
tabela cliente
…
…
O que mais?
Hibernate também dá suporte a tipos
de dados definidos pelo usuário
Interceptadores e EventListeners
Filtros
Definições explicitas dos SQLs de
insert e update e load (hibernate 3)
...e mais um pouco!
Sobre configuração
Como obter um SessionFactory?
Programaticamente
Por arquivo XML
Configuração programática
Configuration cfg = new Configuration()
.setProperty("hibernate.dialect",
"org.hibernate.dialect.HSQLDialect").
.setProperty("hibernate.connection.driver_class",
"org.hsqldb.jdbcDriver")
.setProperty("hibernate.connection.url",
"jdbc:hsqldb:file:hsqldb/data")
.setProperty("hibernate.connection.username", "sa")
.setProperty("hibernate.connection.password", "")
.addClass(Filme.class)
.addClass(Cliente.class)
.addClass(Locacao.class);
SessionFactory sessionFactory = cfg.buildSessionFactory();
Configuração XML
hibernate.cfg.xml
org.hibernate.dialect.MySQLDialect
org.gjt.mm.mysql.Driver
root
ftBBvEdiC
jdbc:mysql://localhost/lockar
Configuration cfg = new Configuration().configure();
SessionFactory sessionFactory = cfg.buildSessionFactory();
Extras
Hbm2ddl (tool)
Gera o schema do BD a partir das XML
de mapeamentos
Usado por linha de comando ou pelo ant
Exercícios
Ampliar nosso modelo
Exercícios
Crie as classes (JavaBeans/POJO)
Crie os XML de mapeamentos
Implemente as consultas e métodos para retornar
Todos os filmes locados durante um determinado mês
Listagem contendo nome do filme, média das avaliações, e
total de comentários para todos os filmes
Listagem contendo nome do filme mais o número de cópias de
VHS e de DVD desse filme
Listagem contendo nome do filme mais o número de cópias de
VHS e de DVD desse filme locadas em um determinado mês
Todos os clientes que locaram mais de 5 VHS no ultimo mês
(Com as devidas locações carregadas)