78 slides que dão uma visão geral sobre o hibernate, que é um framework de mapeamento objeto-relacional para java. os colaboradores da 3Layer Tecnologia, parceiros da JBoss, dão suporte nessa área.
Merlin Um Novo Horizonte Na Criacao Das Telas De Cadastro
Workshop Hibernate Com Comentarios
1. www.3layer.com.br
www.3layer.com.br
Hibernate
Uma visão geral sobre o framework padrão
de fato para mapeamento objeto-relacional
Dezembro de 2006 Hibernate - Uma visão geral sobre o framework padrão De Fato para slide 1 de 78
mapeamento objeto-relacional
Autoria e Conteúdo
AUTOR: Marcelo Mrack – mmrack@gmail.com. 3Layer Tecnologia, Porto Alegre, RS – Brasil. http://www.3layer.com.br,
2006.
CONTEÚDO: Apresentação sobre o framework Hibernate
Sobre os Direitos Autorais
Essa apresentação pode ser copiada e impressa, sendo que qualquer parte de seu conteúdo pode ser reutilizada em
outras obras, públicas ou privadas. Em qualquer caso é necessário manter a referência para o autor acima identificado.
É expressamente proibida a exibição em público desse documento, seja na forma de palestra, workshop, feira ou
qualquer outro evento similar sem o consentimento do autor.
1
2. www.3layer.com.br
Sobre o autor
Marcelo Mrack, mmrack@gmail.com
29 anos, 8 em TI, 6 em Java
Bacharel em C. Computação, UNISC – 2001
Mestrando em C. Computação, UFRGS – 2006
Atuação em projetos web e desktop n camadas
Sócio e arquiteto na 3Layer Tecnologia
Projetista na CWI Software
Consultor e instrutor Hibernate, Java EE
Especialidades: IHC, Patterns, geradores, PU Ágil e UML
http://merlin.dev.java.net
http://telasdecadastro.blogspot.com
Dezembro de 2006 Hibernate - Uma visão geral sobre o framework padrão De Fato para slide 2 de 78
mapeamento objeto-relacional
Sobre o autor
Informações sobre o autor do documento e orador.
2
3. www.3layer.com.br
Sumário
Visão geral
Características gerais
Arquitetura
Funcionamento
Associações, coleções e herança
Cache
HQL
Outras características
Ferramentas e utilitários
Dicas
Comentários finais
Dezembro de 2006 Hibernate - Uma visão geral sobre o framework padrão De Fato para slide 3 de 78
mapeamento objeto-relacional
Sumário
Essa apresentação visa cobrir os aspectos mais essenciais do framework de mapeamento objeto relacional Hibernate,
além de fazer comentários sobre sua utilização e dicas para o desenvolvimento de aplicações.
Os assuntos a serem cobertos estão listados nesse Sumário.
3
4. www.3layer.com.br
Visão geral
O Hibernate é um framework de mapeamento
objeto-relacional para a linguagem Java
Conjunto de classes, interfaces e configuração que
permite simplificar o trabalho de persistir e recuperar
objetos Java em banco de dados relacionais
Hibernate, funcionamento básico
Aplicação Mapeamento Banco de dados
API Hibernate JDBC
Dezembro de 2006 Hibernate - Uma visão geral sobre o framework padrão De Fato para slide 4 de 78
mapeamento objeto-relacional
Visão geral
O Hibernate (http://www.hibernate.org) é um framework para mapeamento objeto-relacional para a linguagem Java.
Na prática, ele é um conjunto de classes, interfaces e arquivos de configuração pré-acabados que permitem a criação
de uma camada de serviço capaz de abstrair a existência do banco de dados para sistemas Java.
Funcionamento básico
Seu processo de funcionamento é simples: Na aplicação Java existe um conjunto de objetos (instâncias de classes
Java) que devem ser persistidos em um meio durável, no caso o banco de dados. O banco de dados nesse caso segue
o modelo relacional (tabelas + relacionamentos) e por esse motivo diz-se que existe uma impedância entre essas
camadas (objetos, propriedades e associações na aplicação; tabelas, colunas e relacionamentos no banco de dados). O
Hibernate atua entre essas camadas, provendo funcionalidades para salvamento e recuperação dos objetos Java no
banco de dados. Para a aplicação Java persistir esses objetos, ela invoca métodos da API do Hibernate. O Hibernate
mapeia esses comandos para os respectivos comandos SQL do banco de dados. Esses comandos são executados sobre
uma conexão JDBC normal previamente configurada no Hibernate. Para recuperação dos objetos, a aplicação cliente
invoca métodos da API do Hibernate que também são traduzidos em comandos SQL do banco de dados, mas agora
para seleção de registros.
Utilizando essa abordagem, além de permitir isolamento da aplicação em relação ao banco de dados, o Hibernate
habilita a independência de banco de dados, uma vez que a aplicação cliente não possui comandos SQL dentro de seu
código. Importante ainda é o fato que todos os comandos SQL gerados pelo Hibernate são nativos do banco de dados
corrente.
4
5. www.3layer.com.br
Degustação
Um exemplo simples de uso do Hibernate
Persistência... NotaFiscal Cliente Endereco
1 NotaFiscal nf = new NotaFiscal(); numero:int
2 nf.setNumero(numero); ... Item Cidade
3 //...outros setters...
4 Produto Estado
5 Session session = HibernateUtil.
6 getSessionFactory().getCurrentSession();
7 Fornecedor Estoque Pais
8 session.beginTransaction();
9 session.save(nf); Produtos Local
10 session.getTransaction().commit();
... ... ...
Recuperação...
1 Session session = HibernateUtil.
2 getSessionFactory().getCurrentSession();
3 NotaFiscal nf = (NotaFiscal) session.load(NotaFiscal.class, 1001);
Dezembro de 2006 Hibernate - Uma visão geral sobre o framework padrão De Fato para slide 5 de 78
mapeamento objeto-relacional
Degustação
Nesse pequeno exemplo, um simples uso do Hibernate.
Persistência
Seja um objeto do tipo NotaFiscal. Deseja-se persistir esse objeto Java em uma base de dados relacional. Na aplicação
cliente, o código é como da listagem superior. É instanciado um objeto NotaFiscal e suas propriedades são definidas
através dos métodos setters. Através de chamadas da API do Hibernate, a fábrica de sessões de trabalho disponibiliza
uma sessão para a aplicação cliente. Essa sessão é usada para persistir o objeto NotaFiscal através do método save().
Nota-se que a chamada ao método save() está encapsulada dentro de uma transação do Hibernate. Isso é um
requisito importante e obrigatório.
Agora, suponha-se o caso que o objeto NotaFiscal possuísse ligações com diversos outros objetos, como Cliente, Item
de nota, Produto, etc. Qual seria o impacto no código da aplicação para persistir todo esse grafo de objetos? A
resposta é nenhum. O Hibernate pode encarregar-se de executar a persitência de todos esses objetos relacionados
(obviamente isso vai depender do tipo de configuração aplicada sobre cada um desses objetos dependentes).
Recuperação
Finalmente, para recuperação do objeto salvo (na mesma ou em outra sessão de trabalho do usuário), o código
também é simples. Obtida uma sessão de trabalho do Hibernate, basta invocar o método load(), passando como
parâmetros o tipo da classe e o identificador (chave primária, por assim dizer) do objeto. O retorno, após uma simples
conversão é atribuído ao objeto NotaFiscal. Também aqui, as dependências de objetos (Cliente, Endereço, etc.)
poderiam ser carregadas junto automaticamente, dependendendo do tipo de configuração adotada.
Transações gerenciadas
Importante é o fato que o encapsulamento de comandos (como o save() ) sob transações pode ser executado de
forma transparente. Isso é possível quando o Hibernate é executado como serviço dentro de ambientes gerenciados
em servidores de aplicação Java EE, como o JBoss. Isso será visto depois.
5
6. www.3layer.com.br
Histórico
O início
Concepção no final de 2001
Projeto pessoal, de Gavin King na Cirrus Technologies, AU
Descontentamento com o modelo J2EE CMP
A evolução
jul/2002 - versão 1.0
inicialização tardia
jan/2003 – versão 2.0
dialeto Oracle 9
jul/2004 – versão 3.0
net.sf.hibernate > org.hibernate
adequação EJB3 (JSR220)
nov/2006 – versão 3.2.1
release corrente
Dezembro de 2006 Hibernate - Uma visão geral sobre o framework padrão De Fato para slide 6 de 78
mapeamento objeto-relacional
Histórico
O projeto Hibernate é de autoria de Gavin King, um desenvolvedor Java que estava insatisfeito com o modelo CMP de
persistência do J2EE 1.3. Descontente com o paradigma da época, propos-se a desenvolver um framework próprio,
que condizia com as necessidades suas e de seus amigos. Por incrível que pareca, ele apostou com seu chefe (gerente
de projeto) que conseguiria fazer algo melhor que o CMP do J2EE. Isso foi o começo, lá pelos idos do ano 2001 na
Austrália.
Evolução
Ao longo dos anos e dos constantes releases da ferramenta no repositório sourceforge (www.sourceforge.net), várias
funcionalidades foram sendo adicionadas e desenvolvedores associando-se ao projeto. De importante impacto foi a
versão 3.0 da ferramenta, onde a revisão do padrão CMP do J2EE estava em desenvolvimento. Nesse momento, as
idéias do framework Hibernate já estavam bem alicerçadas e difundidas pelo planeta. Nesse sentido, o sr. King fora
incluído como membro do JCP da Sun (e parceiros) como um engenheiro especialista e praticamente definiu as bases
no novo modelo CMP do Java EE 1.5 (JSR 244). O Hibernate que não fora baseado em nenhum padrão acabara de
criar um: o Java Persistence API (parte da JSR 220 ou EJB3).
Atualmente (dez/2006), a versão corrente do Hibernate (3.2.1) é bastante estável, escalável, customizável e aderente
às necessidades de desenvolvedodres cliente/servidor e N camadas.
6
7. www.3layer.com.br
Características gerais
Abordagem totalmente OO
Suporte à mais de 20 SGBD
Gera comandos SQL nativos para cada SGBD
Suporte total ao Java 1.5
Opera em ambientes standalone e sob containers
Dezembro de 2006 Hibernate - Uma visão geral sobre o framework padrão De Fato para slide 7 de 78
mapeamento objeto-relacional
Características
O Hibernate objetiva dar ao desenvolvedor a possibilidade de trabalhar de forma totalmente orientada a objetos – não
pensa-se mais em linhas, colunas e tabelas, mas sim em objetos, associações e coleções.
Tendo engines específicas de geração de comandos SQL, o Hibernate conta atualmente com o suporte à mais de 20
banco de dados – em outras palavras, ele pode ser usado em cada um desses SGBDs executando comandos SQL
nativos. Não obstante, como a aplicação cliente opera sobre sua API, a troca de um SGBD por outro não afeta a
camada cliente do sistema (não é necessário reescrever o código do sistema)
Na versão 3, o Hibernate adequou-se à sintaxe 1.5 do Java, suportando enumerações, coleções tipadas, anotações e
outros recursos avançados dessa linguagem.
Quanto ao funcionamento, o serviço do Hibernate pode operar de forma standalone (o Hibernate roda dentro da
aplicação cliente) ou gerenciada (o Hibernate roda dentro de containers Java EE, como o JBoss). Detalhes sobre isso, a
seguir.
7
8. www.3layer.com.br
Características gerais
Alta Performance
2 Níveis de Cache
SQL Nativo
Comandos pré-compilados
Queries nativas com mapeamento automático
Suporte à transações
Standalone, demarcadas explicitamente
Gerenciada por container (XA-Transactions), implícitas
Dezembro de 2006 Hibernate - Uma visão geral sobre o framework padrão De Fato para slide 8 de 78
mapeamento objeto-relacional
Performance
Objetivando escalabilidade, o Hibernate possui um eficiente sistema de cache de 2 níveis (ambos em memória RAM).
Seus comandos SQL nativos podem ser gerados tanto em tempo de execução (durante a chamada do cliente)
quanto em tempo de deployment (o padrão) e são compilados no BD através de chamadas preparadas no driver
JDBC.
Importante salientar que, embora o Hibernate ofereça uma API de busca e persistência de objetos e uma linguagem
própria de consultas (a HQL, discutida a seguir), ele também permite a execução de comandos SQL nativos
diretamente pelo desenvolvedor. Mesmo esses comandos SQL nativos podem contar com os recursos de
materialização automáticos, ou seja, as colunas retornadas pelo comando SQL podem ser mapeadas diretamente e
automaticamente para as propriedades dos objetos da aplicação. Tudo isso é configurável
Transações
O Hibernate exige que qualquer comando de alteração de objetos (insert, update, delete) seja encapsulado em uma
transação. Quando ele é usado na forma Standalone (em aplicações cliente-servidor, por exemplo), é tarefa do
programador demarcar o início e o fim das transações (como apresentado anteriormente).
Já em ambientes gerenciados (dentro de servidores de aplicação), o Hibernate pode delegar a demarcação das
transações para o próprio container. Isso é possível graças a sua aderência ao padrão JTA (Java Transaction API).
Quando isso é feito, o código que usa o Hibernate não precisa abrir o fechar transações, ele simplesmente invoca
os métodos de persistência. O container detecta as operações em execução e automaticamente encapsula-as em
transações XA (*). Por outro lado, caso o desenvolvedor não queira utilizar o padrão JTA dentro de um container,
ele pode informar isso via configuração e continuar demarcando suas transações explicitamente. Nota-se que isso
não é recomendado, devido a complexidade que pode estar envolvida (ambientes complexos, cluster de servidores,
fail over, múltiplos databases, etc.)
(*) Transações XA são um padrão de transações do JTA que permitem funcionalidades como clusterização e replicação
em ambientes complexos. Nota-se que essas transações exigem recursos diversos do container (cache, segurança,
replicação, etc.) e, principalmente o suporte dos drivers JDBC. Muitos drivers JDBC não suportam esse tipo de
operação e, nesse caso, as transações XA são substituídas por transações mais simples. Para mais informações
sobre transações em Java, consulte:
1. http://www.onjava.com/lpt/a/792
2. http://www.onjava.com/lpt/a/852
3. Capítulo sobre transações no Java EE Tutorial, em http://java.sun.com/javaee/5/docs/tutorial/doc/
4. JSR 907 (JTA) - http://www.jcp.org/en/jsr/detail?id=907
5. http://java.sun.com/products/jta/
8
9. www.3layer.com.br
Características gerais
Linguagem própria de consulta
HQL
Semelhante ao SQL
Orientada a Objeto
Muitas funcionalidades embutidas
Configuração flexível
XML
Texto puro (arquivo .properties)
Dezembro de 2006 Hibernate - Uma visão geral sobre o framework padrão De Fato para slide 9 de 78
mapeamento objeto-relacional
HQL
Uma funcionalidade importante oferecida pelo Hibernate é a linguagem HQL (Hibernate Query Language) que suporta
recuperação de objetos via uma sintaxe muito semelhante ao SQL, sendo, porém, orientada a objetos. A HQL é
discutida em mais detalhes a seguir.
Configuração
A configuração do Hibernate é dada por arquivos XML (que definem o comportamento do serviço e os aspectos
relativos ao mapeamento objeto-relacional) e por arquivos texto, que definem aspectos do serviço.
Os arquivos texto podem ser suprimidos quando todas as informações necessárias estão contidas nos arquivos XML.
Entretanto, o uso do arquivo texto é mais simples e menos prolixo, sendo suportado em qualquer situação. Dentro do
pacote de instalação do Hibernate existe um arquivo texto de modelo que pode ser utilizado para os casos mais
tradicionais de configuração. Os arquivos XML são um pouco mais complexos e sensíveis ao contexto de uso
(standalone ou gerenciado) e por isso é necessário uma leitura da documentação do framerwork para maiores
detalhes.
9
10. www.3layer.com.br
Características gerais
Ferramentas e utilitários disponíveis
Utilitários
Geração/atualização da BD
Validação da BD
Plugins para IDEs
Operação visual
Engenharia reversa (geração das classes Java a partir da BD)
Software livre
Grande comunidade
Apoiado pela JBoss (RedHad)
Dezembro de 2006 Hibernate - Uma visão geral sobre o framework padrão De Fato para slide 10 de 78
mapeamento objeto-relacional
Ferramentas
O pacote do Hibernate representa o kernel de mapeamento, mas também possui alguns utilitários inclusos, tanto para
a geração automática da base de dados, como para sua atualização e validação. Ferramentas e plugins para IDEs
estão disponíveis através de outros downloads do site do projeto, as quais permitem operação visual e engenharia
reversa.
Outras características
O Hibernate é um projeto Open Source, mantido por desenvolvedores diversos ao redor do mundo. Apoiado pela
JBoss, que recentemente foi adquirida pela Red Hat, é uma solução robusta e que possui suporte dessa empresa, caso
o cliente necessite (nesse caso, o suporte é pago).
Treinamentos e cursos (com certificação) estão disponíveis na JBoss e também em empresas diversas em vários
países. Também tutorais, fóruns, listas de discussão e amplo material de pesquisa e exemplos de sucesso estão
espalhados pela Internet.
10
11. www.3layer.com.br
Arquitetura
Arquitetura-base do Hibernate
Hibernate, arquitetura-base
Dezembro de 2006 Hibernate - Uma visão geral sobre o framework padrão De Fato para slide 11 de 78
mapeamento objeto-relacional
Arquitetura-base
Na visão mais simplista, a arquiteteura do Hibernate resume-se nessa figura. Ao topo, a aplicação do cliente, com sua
interface de usuário e regras de negócio bem como com os objetos a serem persistidos e as chamadas da API do
Hibernate. Transitando entre essa camada e o serviço do Hibernate estão os objetos a serem persistidos. Na camada
do Hibernate, que é um serviço, estão sua configuração de execução (dada pelo arquivo texto de propriedades e
algum possível XML) e os arquivos de mapeamento, que definem o comportamento do mapeamento objeto-relacional.
Por padrão, esse arquivos de mapeamento são escritos em XML (mas podem ser substituídos por anotações – JSR175,
como será visto adiante). Na parte de baixo, o banco de dados, que efetivamente persiste os dados (objetos traduzidos
em tabelas pelo Hibernate).
Geralmente, essa configuração é usada em aplicações cliente-servidor (tanto desktop: swing+hibernate+bd; e web:
jsp+hibernate+bd+servidor web, como o Tomcat ou Jetty).
11
12. www.3layer.com.br
Arquitetura
A configuração completa
Hibernate em configuração completa
Dezembro de 2006 Hibernate - Uma visão geral sobre o framework padrão De Fato para slide 12 de 78
mapeamento objeto-relacional
Arquitetura completa
Na configuração completa, geralmente utilizada em ambientes gerenciados, o Hibernate se parece com essa figura. Na
parte de cima, o código cliente (que pode ser páginas JSP, um Webservice, uma aplicação desktop, etc.) com seus
objetos a serem persistidos. No container Java EE está o serviço do Hibernate, que é fragmentado em partes:
1. A SessionFactory que é responsável por inicializar o serviço do Hibernate com base na configuração associada e
ligá-lo aos recursos do container, como o JNDI, o JDBC e o JTA.
2. A Session, que é obtida através de uma chamada à fábrica de sessões. Sessions são utilizadas pela camada cliente
para execução dos métodos de persistência e recuperação dos objetos.
3. O serviço de transações do Hibernate delega o uso de transações à fábrica de transações, que pode ou não utilizar
o JTA (conforme configuração)
4. O ConnectionProvider do Hibernate é encarregado de obter as conexões do pool de conexões JDBC oferecido pelo
container e a SessionFactory liga essas conexões a sessão de trabalho do usuário.
Na parte de baixo, o banco de dados.
12
13. www.3layer.com.br
Modos de operação
São dois os modos de operação do Hibernate
Standalone
Comum para sistemas 2 camadas (desktop ou web). Nele, o Hibernate
controla todo o escopo de operação, e a aplicação cliente tem domínio
completo da execução do sistema
Gerenciado
Comum para sistemas n camadas. Nele, o Hibernate é configurado
como um serviço no Servidor de Aplicação, e a aplicação cliente solicita
serviços do framework
Standalone (API Hibernate) Gerenciado (API Java EE)
Aplicação Aplicação
Container
Hibernate
Hibernate
BD BD
Dezembro de 2006 Hibernate - Uma visão geral sobre o framework padrão De Fato para slide 13 de 78
mapeamento objeto-relacional
Modos de operação
Aqui, são mostrados o uso standalone e gerenciado do Hibernate.
Standalone
No modo Standalone, o cliente invoca diretamente métodos da API do Hibernate, que então encarrega-se de acessar o
BD. Transações são marcadas explicitamente pelo usuário. Aqui, o código cliente depende da API do Hibernate.
Gerenciado
No modo Gerencaido, o cliente invoca (ou pelo menos é o recomendado invocar) métodos da API de persistência do
Java (JSR220), que está disponível no container Java EE. Esses métodos são delegados ao Hibernate que faz o acesso
ao banco de dados (*). Essa configuração permite que o container Java EE substitua o Hibernate por outro framework
de mapeamento e o cliente continue operando sem maiores complicações (ou seja, sem reescrita de código).
(*) Na verdade, o que acontece é que o padrão Java Persistence (JSR220) é uma fachada de classes e interfaces, mas
sem uma implementação de fato. O Hibernate implementa essa fachada. Assim, o cliente invoca métodos da fachada
Java Persistence e é por isso que ele tem independência de framework de mapeamento. Substituir o Hibernate por
outro framework é uma tarefa mais simples com essa abordagem.
13
14. www.3layer.com.br
Funcionamento
Em suma, o funcionamento do Hibernate é:
1. Para cada objeto do sistema, existe uma configuração
de mapeamento, na forma:
classe <> tabela
propriedade <> coluna | relacionamento
2. Para cada base de dados, existe um arquivo de
configuração que define:
Parâmetros de conexão
Pool
Comportamento padrão
etc.
3. Para persistir e recuperar objetos, a aplicação utiliza sua
API
Dezembro de 2006 Hibernate - Uma visão geral sobre o framework padrão De Fato para slide 14 de 78
mapeamento objeto-relacional
Funcionamento
Três são os passos necessários para utilizar o Hibernate:
1. Criar os arquivos de mapeamento, que definem, em suma relações entre classes e tabelas e entre propriedades e
colunas ou relacionamentos.
2. Definir o arquivo de configuração do serviço, que engloba informações como valores de conexão, usuário, senha,
tamanho do pool, sintaxe do banco de dados e outros.
3. Criar a aplicação cliente que utiliza a API do Hibernate para persistir e recuperar objetos na base de dados.
14
15. www.3layer.com.br
Modelo de desenvolvimento
O processo de desenvolvimento com o Hibernate pode ser de
duas formas:
TopDown: Modela-se OO e gera-se a base
Modela-se as classes do sistema
Cria-se os arquivos de mapeamento e configuração
Gera-se a base de dados
Usa-se a API para persistir e recuperar objetos
BottomUp: Dada uma BD existente, geram-se os artefatos
Efetua-se a engenharia reversa de uma BD via plugin Hibernate Tools,
gerando-se:
– classes Java, arquivos de mapeamento e configuração
Ajusta-se o mapeamento, as classes e a configuração (se necessário)
Usa-se a API para persistir e recuperar objetos
Dezembro de 2006 Hibernate - Uma visão geral sobre o framework padrão De Fato para slide 15 de 78
mapeamento objeto-relacional
Modelo de desenvolvimento
Duas são as formas de desenvolver aplicações com o Hibernate:
TopDown
É o mais recomendado para aplicações criadas “do zero”, ou seja, sem uma base de dados pré-existente. Nesse tipo de
desenvolvimento, a modelagem e construção do sistema segue os padrões OO. Uma vez criadas e definidas quais
classes devem ser persistidas, é aplicado o processo de mapeamento, seja através do XML ou com anotações sobre
essas classes (ambos processos podem ser automatizados com ferramentas visuais, como o plugin Hibernate Tools;
com o uso de máquinas de template, como o Velocity; com scritps de construção, como o Ant; com o uso de IDEs
inteligentes, como o Eclipse e seus templates de código ou através da tecnologia MDA, como o AndroMDA). Mapeadas
as classes, os utilitários de geração do prórprio Hibernate podem gerar a DDL do banco de dados, tanto para sua
criação como para atualização (incremental somente). Feito isso, cria-se a camada cliente, que utiliza a API do
Hibernate para persistir e recuperar os objetos do sistema. Esse modelo pode ser incremental (e geralmente o é) e
escala bem para vários ambientes.
BottomUp
Aqui, presume-se a existência de uma base de dados legada e deseja-se criar uma nova camada cliente, reusando as
tabelas e relacionamentos existentes no BD. Nesse caso, podem ser utilizadas ferramentas de engenharia reversa o
próprio Hibernate Tools (plugin do Eclipse) ou o Middlegen (utilitário para geração de artefatos a partir da base de
dados) para gerar os arquivos de mapeamento, as classes Java de persistência, bem como a configuração-base do
serviço do Hibernate. Com o correto ajuste das informações geradas, é possível fechar o roundtrip de desenvolvimento
e assim utilizar a API do Hibernate para persistir e recuperar objetos na base de dados.
IMPORTANTE é salientar que a abordagem BottomUp não é recomendada para desenvolviementos novos. Ou seja, não
é recomendável em um projeto novo criar o modelo ER (com uma ferramenta como o ERWin, por exemplo) e depois
aplicar uma engenharia reversa sobre a base de dados para então gerar as classes Java do sistema. Isso porque muita
informação (semântica de negócio) é perdida nesse processo e as classes geradas deixam de representar o conceitos
reais da aplicação em construção. É mais interessante incentivar a cultura da modelagem e projeto OO, pois como o
próprio nome diz, trasta-se de um framework de mapeamento Objeto-Relacional e não Relacional-Objeto!
15
16. www.3layer.com.br
Classes de persistência
O Hibernate não força nenhuma regra sobre os
objetos a serem persistidos, porém, algumas práticas
são “fortemente” recomendadas:
Seguir o modelo POJO, onde:
Construtor vazio, no mínimo com visibilidade de pacote
Métodos getters/setters públicos padrões
– (nada além de return this.x e this.x = x)
Fields não públicos
Providenciar um atributo identificador (ID)
Não usar classes final
Dezembro de 2006 Hibernate - Uma visão geral sobre o framework padrão De Fato para slide 16 de 78
mapeamento objeto-relacional
Classes de persistência
O Hibernate não exige nenhuma regra sobre as classes a serem persistidas. Não é preciso estender nenhuma classe,
nem implementar interfaces ou seguir padrões, porém...
...é fortemente recomendado seguir algumas diretrizes, que visam, objetivamente, aumentar a performance, a
escalabilidade, a independência e a facilidade de uso de todo o sistema.
As diretrizes são simples:
1. Seguir o modelo POJO (Plain Old Java Objects), que também é uma diretriz para a Java Persistence API;
2. Providenciar um atributo identificador para a classe;
3. Não declarar classes FINAL, uma vez que benefícios da instrumentação de código (como otimização de acesso)
não vão estar disponíveis.
Dito isso, nada mais espera-se das classes de persistência.
16
17. www.3layer.com.br
O processo de mapeamento
A configuração do mapeamento OO-ER é feita por
classe, através de:
Usando anotações
XML
Anotações (JSR175) (exige pacote extra)
Hibernate, mapeamento de classes
Usando XML
@MinhaClasse classe=tabela
@ id:long XML propriedade=coluna
@ numero:long ...
... ...
Dezembro de 2006 Hibernate - Uma visão geral sobre o framework padrão De Fato para slide 17 de 78
mapeamento objeto-relacional
Mapeamento
Mapear objetos significa definir quais são as relações entre as classes e as tabelas e entre as propriedades e colunas
ou relacionamentos. Isso pode ser feito via arquivos XML ou via anotações (JSR175).
O mapeamento via arquivos XML é o tradicional, desde a versão 0.x do framework. O mapeamento via anotações está
disponível para a versão 3+ do framework que opera sobre o Java 1.5.
Escolher entre usar XML ou anotações é uma opção do desenvolvedor. Nota-se, porém, que as anotações exigem o
download de outro arquivo do Hibernate, o Hibernate Annotations, que nada mais é do que um arquivo JAR a ser
colocado no diretório de bibliotecas do sistema.
17
18. www.3layer.com.br
O Hibernate e os IDs
Uma vez que objetos são recomendados a terem
um ID, o Hibernate encarrega-se de gerenciá-los
Para isso são usados algoritmos de geração:
identity
native
increment
uuid
etc.
Cada algoritmo tem uma aplicação específica
increment não deve ser usado em cluster, por exemplo
Dezembro de 2006 Hibernate - Uma visão geral sobre o framework padrão De Fato para slide 18 de 78
mapeamento objeto-relacional
Identificadores de objetos
Embora não seja necessário, é altamente recomenado o uso de idendificadores para os objetos. São as chaves
primárias do modelo relacional.
Usar chaves primárias otimiza o desempenho do sistema, facilita a localização de objetos e evita problemas de
duplicidade de objetos.
Uma vez que são utilizados identificadores, o Hibernate pode efetuar a geração dos valores para esses idendificadores.
Para isso ele oferece algoritmos de geração diversos. Cada algoritmo tem um uso específico e a escolha correta
depende do tipo de aplicação e ambiente de execução.
Para maiores informações sobre cada algoritmo de geração, consulte a documentação do Hibernate.
18
19. www.3layer.com.br
O modelo OO e o Hibernate
O Hibernate suporta completamente o modelo OO
do Java, incluindo
Associações simples e bidirecionais
Coleções
Herança
Interfaces
Tipos de dados nativos e wrappers
Objetos simples e compostos
Atributos estáticos
Enumerações
Qualquer tipo definido pelo usuário
Dezembro de 2006 Hibernate - Uma visão geral sobre o framework padrão De Fato para slide 19 de 78
mapeamento objeto-relacional
Hibernate versus Modelo OO
Em suma, todo e qualquer estrutura da linguagem Java pode ser persistida, incluindo coleções, enumerações, classes
com herança, interfaces, tipos nativos ou wrappers e, obviamente, tipos definidos pelo usuário.
19
20. www.3layer.com.br
Associações
Unidirecionais
A referencia B
Bidirecionais
A referencia B que referencia A
Associação unidirecional Associações bidirecionais
esposa
Crianca
Estado
dono bichinho Pessoa
Pais
pais AnimalDeEstimacao esposo
Dezembro de 2006 Hibernate - Uma visão geral sobre o framework padrão De Fato para slide 20 de 78
mapeamento objeto-relacional
Associações
Uma associação é uma ligação entre um objeto e outro. Ela ocorre quando uma classe declara um atributo que é do
tipo de outra classe, ambas persistentes.
Associações podem ser unidirecionais (somente o objeto que declara a associação – ou principal – tem conhecimento
da associação) ou bidirecional (quando ambos objetos têm referências mútuas e, consequentemente, ambos têm
conhecimento da associação).
Associações auto-associativas quando o atributo declarado é do mesmo tipo da classe declarante, como no exemplo da
Pessoa, que possui dois auto-relacionamentos.
20
21. www.3layer.com.br
Associações e o modelo relacional
Associações são mapeadas para o modelo relacional
através de um chave estrangeira na tabela
equivalente à classe que declara a associação
Associação unidirecional Modelo relacional correspondente
Estado Estado Pais
id (PK) id (PK)
nome nome
Pais pais (FK)
pais
Dezembro de 2006 Hibernate - Uma visão geral sobre o framework padrão De Fato para slide 21 de 78
mapeamento objeto-relacional
Associações no modelo relacional
Associações no modelo relacional são mapeadas para chaves estrangeiras na tabela equivalente à classe que declara a
associação, como no exemplo da figura.
21
22. www.3layer.com.br
Coleções
Um objeto A referencia uma coleção de objetos B
Exemplo de coleções
Unidirecional Bidirecional
estados estados
Estado Estado
pais
Pais Pais
Dezembro de 2006 Hibernate - Uma visão geral sobre o framework padrão De Fato para slide 22 de 78
mapeamento objeto-relacional
Coleções
Quando uma classe declara um atributo que referencia um grupo de objetos identicos, diz-se que isso é uma coleção.
Da mesma forma que nas associações, as coleções podem ser unidirecionais ou bidirecionais. No exemplo acima, estão
ambas situações. Na unidirecional, somente a classe Pais tem conhecimento da relação; já na bidirecional, ambas
classes têm conhecimento da relação.
22
23. www.3layer.com.br
Coleções e o modelo relacional
Coleções podem ser mapeadas através de chaves
estrangeiras, ou via tabelas intermediárias
Possíveis mapeamentos
Via chave estrangeira
Coleção bidirecional Estado Pais
id (PK) id (PK)
estados nome nome
Estado pais (FK)
pais
Pais Via tabela associativa
Estado PaisEstado Pais
id (PK) paisId (FK) id (PK)
nome estadoId (FK) nome
Dezembro de 2006 Hibernate - Uma visão geral sobre o framework padrão De Fato para slide 23 de 78
mapeamento objeto-relacional
Coleções no modelo relacional
Coleções são mapeadas para o modelo relacional através de uma chave estrangeira na tabela destino da relação. Por
exemplo, sendo a coleção de Estados de um Pais, na tabela equivalente à classe Estado existirá uma chave estrangeira
que indica o País a que o Estado pertence. Mesmo para coleções bidirecionais a chave estrangeira basta para dar a
informação sobre o objeto principal da relação, no caso o Pais. Esse é o comportamento padrão do Hibernate para o
mapeamento de coleções.
Deixando o padrão de lado e usando o recomenado
Embora o uso de chaves estrangeiras seja suficiente para mapear coleções unidirecionais e bidirecionais, o Hibernate
sugere (e recomenda) o uso de uma tabela associativa para resolver a coleção, como na parte de baixo da figura onde
existem três tabelas. Nessa configuração, não existem chaves estrangeiras nas tabelas equivalentes às classes
envolvidas na coleção. Uma terceira tabela é criada e ela contém as chaves primárias das classes relacionadas. Essas
chaves primárias são também chaves estrangeiras que referenciam as tabelas equivalentes aos relacionamentos.
Com essa abordagem, é possível efetuar modificações nas coleções (como mudar a cardinalidade de 1-n para n-n) sem
a necessidade de ajustes no banco de dados. Além disso, deixa o banco de dados preparado para outras necessidades,
como associar dados a itens da coleção. Isso é visto a seguir.
23
24. www.3layer.com.br
Relacionamentos múltiplos (n-n)
Muitas vezes, os relacionamentos entre as classes
podem ter cardinalidade maior que 1, nesse caso:
Modelo OO Modelo ER
Sem informações por item Sem informações por item
alunos
Aluno Aluno AlunoDisciplina Disciplina
disciplinas id (PK) alunoId (FK) id (PK)
nome disciplinaId (FK) nome
Disciplina
Com informações por item Com informações por item
turma
Aluno Turma Disciplina
Aluno Turma
alunos nome (PK)
turmas id (PK) id (PK)
alunoId (FK)
nome nome
disciplinas disciplinaId (FK)
Disciplina horario
Dezembro de 2006 Hibernate - Uma visão geral sobre o framework padrão De Fato para slide 24 de 78
mapeamento objeto-relacional
Relacionamentos n-n
O suporte aos relacionamentos n-n no Hibernate é feito através de tabelas de associação, como no exemplo acima.
Sendo um aluno que frequenta várias disciplinas e cada disciplina consistida de vários alunos, constitui-se um
relacionamento n-n, onde cada parte da relação compreende uma coleção de objetos.
Quando dados devem ser vinculados a itens da coleção, esses são armazenados na tabela associativa. É o caso, por
exemplo, da formação de turmas de alunos por disciplina. Nesse caso, define-se já no modelo de objetos o conceito de
Turma e, para cada uma, associa-se as informações necessárias, como a nota do aluno.
24
25. www.3layer.com.br
Carregamento de dependências
Associações e coleções podem ser carregadas de
duas formas:
Antecipadamente: Quando o objeto principal é
carregado, a associação (ou coleção) também o é.
Tardiamente: Quando o objeto principal é carregado, a
associação (ou coleção) não o é.
Carregamento de dependências
estados Antecipado Tardio
Estado
Pais p = (Pais) session.load(Pais.class,123); Pais p = (Pais) session.load(Pais.class,123);
//p.getEstados() inicializada //p.getEstados() não inicializada
Pais
Dezembro de 2006 Hibernate - Uma visão geral sobre o framework padrão De Fato para slide 25 de 78
mapeamento objeto-relacional
Dependências
Quando um objeto recuperado da base de dados possui associações ou coleções, essas podem ou não ser
materializadas junto com esse objeto.
Quanto as dependências são inicializadas junto ao objeto que as declara, ocorre o chamado carregamento antecipado..
Quanto as dependências não são inicializadas junto ao objeto que as declara, ocorre o chamado carregamento tardio.
O comportamento do carregamento das dependências é configurável através da propriedade LAZY, geralmente com
valores True ou False (e algumas variações) em cada propriedade da classe.
Para associações, o carregamento padrão é tardio com o uso de um proxy gerado em tempo de execução (via
instrumentação de código) que inicializa a associação no seu primeiro acesso (chamada do método getter). Para
coleções, o carregamento padrão é o tardio.
25
26. www.3layer.com.br
Mais sobre coleções
Coleções podem ser indexadas ou não
Coleções indexadas exigem uma coluna a mais (de
ordem) na tabela destino
Coleções podem ser ordenadas
explicitamente
Durante o mapeamento, é possível especificar uma
ordem de busca via ORDER BY
Coleções podem ter comandos customizados
de carregamento
O padrão de busca é uma junção entre as tabelas, mas
pode ser explicitado um comando diferente
Dezembro de 2006 Hibernate - Uma visão geral sobre o framework padrão De Fato para slide 26 de 78
mapeamento objeto-relacional
Mais coleções
Coleções podem ser indexadas. Isso ocorre quando a ordem dos itens da coleção é importante. Nesse caso, uma
coluna extra é adicionada na tabela respectiva ao mapeamento.
Coleções podem ter uma ordem explícita de retorno, obtida através de uma seleção com a cláusula ORDER BY definida
no arquivo de mapeamento.
Coleções podem ter uma forma diferente de carregamento. Por padrão, uma junção é feita entre a tabela que
representa a classe principal e a tabela que representa a classe do item da coleção. Porém, é possível utilizar um
comando HQL customizado para inicialização dessa coleção, ou mesmo SQL e até Stored Procedures para isso.
26
27. www.3layer.com.br
Integração com JMX
O Hibernate suporta o gerenciamento de serviço
através da tecnologia JMX, padrão no Java EE
Através dela é possível verificar o estado das sessões
de trabalho, da fábrica de sessões, estatíticas de
cache, log, etc.
Utilitários visuais podem ser encontrados na web, ou
construídos conforme a necessidade JMX Console
52ms
Min
29ms
Max
12ms Avg
4
Erros
Dezembro de 2006 Hibernate - Uma visão geral sobre o framework padrão De Fato para slide 27 de 78
mapeamento objeto-relacional
JMX
JMX (Java Management eXtensions) é um padrão Java para gerenciamento e monitoramento de serviços, muito
utilizado em containers de aplicações. O Hibernate está preparado para suportar essa tecnologia.
Para mais informações sobre JMX consulte http://java.sun.com/javase/6/docs/technotes/guides/jmx/index.html.
27
28. www.3layer.com.br
Cache
O Hibernate possui um mecanismo robusto de
cache para os objetos da aplicação, dividido em
dois níveis Esquema de cache do Hibernate
Cache de primeiro nível
(por sessão)
Cache de segundo nível
(por serviço)
BD
Dezembro de 2006 Hibernate - Uma visão geral sobre o framework padrão De Fato para slide 28 de 78
mapeamento objeto-relacional
Cache
O Hibernate conta com um exclusivo sistema de cache de 2 níveis, configurável e plugáve.
O cache é utilizado para armazenar, temporária ou indefinidamente, objetos utilizados (persistidos e recuperados)
durante o uso da aplicação.
Mais detalhes a seguir.
28
29. www.3layer.com.br
Cache de primeiro nível
O cache de primeiro nível é automático, e seu
escopo é a sessão de trabalho
Cada objeto persistido ou recuperado durante uma
sessão é cacheado e está disponível para todos clientes
que acessarem essa mesma sessão
Quando a sessão é finalizada, os objetos são liberados
Dezembro de 2006 Hibernate - Uma visão geral sobre o framework padrão De Fato para slide 29 de 78
mapeamento objeto-relacional
Cache de primeiro nível
O cache de primeiro nível é transparente e seu escopo é a sessão de trabalho. Isso significa que, enquanto a sessão
estiver aberta, todo e qualquer objeto que passar por ela (vindo do ou indo para o BD) será atachado ao cache e é
utilizado para evitar acessos desnecessários ao banco de dados. Mesmo quando a sessão de trabalho ocorre sobre um
ambiente clusterizado o cache de primeiro nível está disponível.
O cache de primeiro nível é o primeiro acessado peo Hibernate e opera exclusivamente em memória.
29
30. www.3layer.com.br
Cache de segundo nível
O cache de segundo nível é configurável, e seu
escopo é variável
Objetos e coleções podem ser cacheadas através de várias
maneiras, via configuração
Diversos engines de cache são suportados:
Hashtable, EHCache, SwarmCache, JBoss TreeCache
Características diferentes quanto à clusterização, invalidação,
suporte à transações, etc.
ReadOnly, ReadWrite, nonStrict ReadWrite, Transactional
Queries podem, explicitamente, abdicar do cache
Dezembro de 2006 Hibernate - Uma visão geral sobre o framework padrão De Fato para slide 30 de 78
mapeamento objeto-relacional
Cache de segundo nível
O cache de segundo nível pode operar em memória e também ser persistido em disco. Graças à sua arquitetura,
diferentes engines de cache podem ser utilizadas, cada qual com recursos e performance diferenciados.
Um cache de segundo nível é acessado sempre depois do cache de primeiro nível e seu escopo de duração é definido
pela configuração. Nele podem existir tanto objetos (grafos) completos como coleções isoladas.
O cache de segundo nível pode operar na forma somente leitura (útil para dados imutáveis) como na forma de leitura
e escrita, tendo timeouts configuráveis e podendo ser compartilhados e replicados em ambientes clusterizados.
Eventualmente, as queries do usuário podem decidir não utilizar o cache de segundo nível (ou seja, o select é feito
diretamente na base de dados). Isso é definido via configuração em nível de serviço.
30
31. www.3layer.com.br
Cache, um exemplo
Configuração do cache de segundo nível
Pode ser dada por XML, anotações ou por arquivo externo
Configuração básica de um cache usando a engine EhCache
Dimensionar os dados no cache é importante, levando
em consideração acessos, média de preenchimento dos
objetos, memória disponível e tipo de retenção
Usando anotações para especificar parâmetros de cache
Dezembro de 2006 Hibernate - Uma visão geral sobre o framework padrão De Fato para slide 31 de 78
mapeamento objeto-relacional
Um exemplo de cache
Nessa figura, um exemplo do uso de cache de segundo nível.
Nota-se que sua configuração pode ser bem detalhada e ser realizada através de XML ou de anotações sobre a classe
ou coleção.
IMPORTANTE é o fato que os caches devem ser dimensionados corretamente, levando em consideração aspectos
como o tipo de acesso aos objetos, carga de dados, timeout de invalidação e necessidade de persistência em disco.
31
32. www.3layer.com.br
Transações
Todas as operações executadas no Hibernate são
encapsuladas por transações
Standalone, transações demarcadas pelo usuário
No container, podem ser automatizadas via JTA pelo
Servidor de Aplicação
Chamada típica em container
Modo Standalone Modo gerenciado EJB1 EJB2 EJB3 HIbernate
1. getSession() 1. getSession() 1 2 3
2. beginTransaction() 2. persist() 4 5
3. persist() 6
4. commit() 7
5. closeSession() 8
9
Dezembro de 2006 Hibernate - Uma visão geral sobre o framework padrão De Fato para slide 32 de 78
mapeamento objeto-relacional
Transações
Como dito, todas operações executadas pelo Hibernate são encapsuladas por transações.
Na figura à esquerda, o modo Standalone evidencia que é o código do usuário o responsável por demarcar o início e o
fim de uma transação.
Ao centro, a figura mostra um típico código de persistência em um ambiente gerenciado (dentro de um container Java
EE). Nota-se que não existe código de usuário para demarcar a transação. Essa tarefa é realizada automaticamente
pelo container Java EE.
À direita, a representação gráfica de uma chamada de um cliente para execução de uma transação. O EJB1 é um EJB
de fachada que executa uma série de operações sobre outros EJBs que acessam várias vezes o Hibernate (executando
possivelmente comandos de persistência e recuperação de objetos). Quando o método principal do EJB de fachada
retornar o container detecta que a transação de negócio terminou e então ele confirma a transação do Hibernate. Tudo
isso é automático e transparente.
Obviamente, o programador pode decidir não usar transações gerenciadas dentro do container, mas isso é uma prática
não recomendada.
IMPORTANTE salientar que transações não podem ser aninhadas.
32
33. www.3layer.com.br
Interceptadores
São objetos que podem ser anexados à uma sessão
de trabalho e executar ações diversas
Útil, para execução de operações administrativas, de
segurança e auditoria
Utilizando um interceptor para adicionar entradas de log
OrdemDeCompra
Hibernate BD
oc.setNumero(); UPDATE()
numero : int oc.setData();
data : Date oc.addItens(); is OrdemDeCompra {
itens : List<Item> sess.save(oc); oc.setOperador()
operador : String }
LogInterceptor
onUpdate()
Dezembro de 2006 Hibernate - Uma visão geral sobre o framework padrão De Fato para slide 33 de 78
mapeamento objeto-relacional
Interceptadores
Os interceptadores são objetos que executam ações pré-determinadas antes ou depois de um evento na sessão de
trabalho. Um uso típico é para cobrir aspectos verticais do sistema, como log e auditoria.
No exemplo, o código cliente instancia e salva um objeto sem, porém, informar qual o operador do sistema está
fazendo isso. O interceptador captura o evento de salvamentdo desse objeto e insere as informações de log
necessárias. O objeto então é persistido no banco de dados. Todo esse funcionamento é transparente para o código
cliente.
Interceptadores são criados através da implementação da interface org.hibernate.Interceptor.
33
34. www.3layer.com.br
Cascateamento de operações
Por padrão, nenhuma operação de cascateamento é
executada. Porém, isso pode ser alterado, conforme as
necessidades da aplicação, sendo:
Nenhuma
Inclusão Cascateando operações
Atualização root
SAVE-UPDATE ALL
Remoção MERGE
Todas a b c d
Todas, removendo órfãos
NONE
Limpeza (de cache) DELETE ALL
ALL
Fusão (em sessão) g
e f
ou combinações válidas EVICT
ALL, DELETE-ORPHAN
Dezembro de 2006 Hibernate - Uma visão geral sobre o framework padrão De Fato para slide 34 de 78
mapeamento objeto-relacional
Cascateamento de operações
Quando um objeto possui dependências, qualquer operação que ocorre sobre esse objeto pode implicar em outras
operações nas suas dependências. Por exemplo, ao salvar o objeto NotaFiscal, deseja-se salvar também seus Itens.
Por outro lado, ao atualizar um objeto Endereço não é interessante atualizar o objeto Cidade relacionado, uma vez que
a cidade já deve estar previamente cadastrada no sistema.
Muitas outras situações podem ocorrer e, para cada uma delas o Hibernate habilita ou não o cascateamento dessas
operações.
34
35. www.3layer.com.br
Herança
O Hibernate suporta o mapeamento da herança de
três formas:
Uma tabela por hierarquia
Uma tabela por subclasse Uma tabela por hierarquia
Uma tabela por classe concreta SerVivo
id | nome | temp | caule | TIPO
Hierarquia de classes
Uma tabela por subclasse
SerVivo
id SerVivo Animal Vegetal
nome id | nome id (FK) | temp id (FK) | caule
Uma tabela por classe concreta
Animal Vegetal
SerVivo Animal Vegetal
temp caule id | nome id | nome | temp id | nome | caule
Dezembro de 2006 Hibernate - Uma visão geral sobre o framework padrão De Fato para slide 35 de 78
mapeamento objeto-relacional
Herança
A diferença mais notável entre o modelo OO e o relacional é o suporte à herança, disponível somente para os sistemas
orientados a objeto.
Estruturas que envolvem herança podem ser mapeadas para o modelo relacional de três formas:
1. Uma tabela por hierarquia. Nesse caso, uma única tabela armazena todos objetos da hierarquia inteira de classes.
Isso traduz-se em uma tabela que possui todos as propriedades de todas as classes da hierarquia + um atributo
identificador, o qual determina qual o tipo de objeto salvo na linha de registro. Essa configuração exige menor
número de tabelas no banco de dados, mas exige que as colunas da tabela permitam valores nulos, sendo que,
sempre existirâo entradas nulas quando a árvore se especializar.
2. Uma tabela por subclasse. Cada classe (incluindo a raiz) é mapeada para uma tabela distinta, sendo que, cada
tabela, possui colunas referentes aos atributos existentes na classe somente (em outras palavras, os atributos
herdados não estâo presentes na tabela). Como consequência, não é obrigatório a existência de entradas nulas na
tabela, porém, a recuperação de um objeto exige a junção entre todas as tabelas, desde a raiz até a classe do
objeto a ser recuperado.
3. Uma tabela por classe concreta. Nesse caso, cada classe é mapeada para uma tabela e, cada tabela, possui todos
os atributos da classe + os atributos herdados. Aqui, não existe obrigatoriedade da nulidade nas colunas e não são
necessárias junções entre tabelas para recuperação/persistência de objetos. Entretanto, atributos herdados não
podem ser sobreescritos (em outras palavras, o campo nome do SerVivo não pode ser renomeado para outro nas
classes derivadas).
Embora o Hibernate suporte algumas variações nesse modelo, essa é o processo básico de mapeamento, todo
configurável pelos arquivos XML ou anotações. Cabe ao desenvolvedor identificar a melhor solução para cada caso.
35
36. www.3layer.com.br
HQL – Conceito
O Hibernate possui uma linguagem própria para
recuperação dos objetos armazenados na base de
dados, é a HQL
Não segue nenhuma especificação
Mas deu origem a uma: a EJB-QL do Java EE
Projetada para ser simples e poderosa
Mais direta que o SQL
Menos complexa que a OQL
Dezembro de 2006 Hibernate - Uma visão geral sobre o framework padrão De Fato para slide 36 de 78
mapeamento objeto-relacional
HQL – Conceito
O framework de persistência Hibernate disponibiliza junto com ele uma linguagem de consulta de objetos.
Originalmente projetada para executar buscas na base de dados, na versão 3.0 o suporte a operações de manipulação
de dados (Data Manipulation Language – DML) foi adicionado.
Embora não siga nenhuma especificação, sua estrutura é muito bem definida, sendo compatível com aplicações
desenvolvidas desde as primeiras versões do framework. De tanto sucesso, o HQL acabou tornando-se referência na
definição do padrão EJB3-QL, este sim uma linguagem de objetos baseada na especificação Enterprise JavaBeans 3.
No tocante à estrutura da linguagem, o HQL foi propositalmente projetado para ser parecido com o SQL, mas
suportando o conceito de objetos. Logo à primeira vista nota-se grande semelhança com as estrutruras SQL, como
SELECT, FROM e WHERE. Comparado à OQL, o HQL é menos complexo e ao mesmo tempo oferecendo muito mais
recursos, como funções padrão e operações diversas.
36
37. www.3layer.com.br
HQL – Características
Opera sobre o serviço do Hibernate
Mapeia seus comandos para SQL nativos, ou seja, os
dialetos do BD em uso no momento
Vale-se de recursos de cache de primeiro e
(opcional) segundo níveis
Possui sintaxe semelhante ao SQL, para reduzir a
curva de aprendizagem
Dezembro de 2006 Hibernate - Uma visão geral sobre o framework padrão De Fato para slide 37 de 78
mapeamento objeto-relacional
HQL – Características
O HQL não é executado diretamente no banco de dados. Ele é executado sobre o serviço do Hibernate. Embora à
primeira vista isso pode transparecer como sendo um processo mais lento, uma vez que mais uma camada existe entre
a aplicação e o BD, na verdade isso não ocorre.
Durante a execução, os comandos HQL são mapeandos para a versão SQL nativa do banco de dados utliizado, ou seja,
o dialeto do próprio banco de dados é utilizado. Isso traduz-se em performance, pois estruturas otimizadas de acesso
podem ser utilizadas. Além disso, executando sobre o serviço do Hibernate, os comandos HQL podem valer-se das
estruturas de cache que o Hibernate utiliza, tanto em primeiro quanto em segundo nível.
Caches de primeiro nível são montados e mantidos durante uma sessão de serviço, geralmente uma transação do
banco de dados (uma query com subselects se enquadra nesse caso). Caches de segundo nível são criados através da
configuração do serviço e replicam em memória (no servidor de aplicação, onde o serviço do Hibernate está sendo
executado) os dados existentes nas tabelas do banco de dados. Caches de segundo nível podem ser distribuiídos em
cluster de servidores, sendo altamente otimizados (devido estrutura de hashmaps hierárquicos) e seguros.
Como o HQL é muito semelhante ao SQL, sua curva de aprendizagem é muito menor que qualquer outra linguagem de
consulta de objetos, como o OQL. Isso permite uma maior assimilação do HQL junto a comunidade de
desenvolvedores. Além disso, como comentado, o HQL é a base do EJB3-QL, mais um motivo para sua grande
aceitação.
37
38. www.3layer.com.br
HQL – Características
Efetua consulta de objetos ou propriedades
Possui suporte à herança (consultas polimórficas)
Permite fácil navegação entre associações de
objetos
Além dos tipos de usuário, opera sobre tipos java
nativos ou wrappers
String, boolean, Date, etc.
Coleções Java e de usuário
List, Set, Collection, Map, SortedSet, SortedMap
Implementando org.hibernate.usertype.UserCollectionType
Dezembro de 2006 Hibernate - Uma visão geral sobre o framework padrão De Fato para slide 38 de 78
mapeamento objeto-relacional
HQL – Características
Embora o HQL seja uma linguagem para consulta de objetos, ele pode ser usado para recuperar estruturas semi-
estruturadas, como atributos de objetos.
Devido sua característica OO, o suporte a estruturas baseadas em herança é muito facilitada. Consultas polimórficas
(ou seja, executadas sobre estruturas com herança) podem ser efetuadas como qualquer outra consulta, sem
necessidade de adição de nenhuma palavra-chave adicional ou mesmo execução de junções.
Outra característica importante do HQL é o suporte a navegação sobre associações de objetos, usando tão somente o
caractere “.” (ponto). Por exemplo, uma declaração como “pessoa.cidade.uf.pais.continente.nome” significa que o
comando de busca deve retornar o nome do continente em que a pessoa esta localizada, usando as associações
existentes, as quais permitem a navegação desde a pessoa até o continete. Isso funciona para atributos com qualquer
visibilidade.
Quanto aos tipos de dados suportados, outra vantagem para o HQL. Como ele é projetado especificamente para a
linguagem Java, seus tipos de retorno não precisam ser convertidos, pois são tipos nativos da linguagem, com String,
boolean e List.
38
39. www.3layer.com.br
HQL – Funcionalidades
Possui inúmeras funções, como no SQL
Agregação
SUM
AVG
MIN
MAX
COUNT
Expressões
IN, NOT IN, BETWEEN, IS NULL, IS EMPTY, etc.
Estruturas CASE (case ... when ... then ... else ... end)
Funções de tempo: current_date(), minute(), etc.
Dezembro de 2006 Hibernate - Uma visão geral sobre o framework padrão De Fato para slide 39 de 78
mapeamento objeto-relacional
HQL – Funcionalidades
Entre as funcionalidades do HQL cita-se um grande número de funções, como as presentes no SQL. Exemplos são
funções de agregação (SUM, COUNT…) e expressões como NOT IN, IS NULL, etc. Além disso, funções extras são
oferecidas, como as temporais.
O suporte a estruturas mais complexas, como o CASE estruturado do SQL também está presente.
39
40. www.3layer.com.br
HQL – Funcionalidades
Mais expressões
Qualquer operação definida pelo EJB3-QL
substring(), trim(), lower(), upper(), etc.
Funções escalares
sign(), trunc(), rtrim(), sin(), etc.
Funções para coleções
size(), minelement(), maxelement(), minindex(), etc.
Qualquer variável estática pública do Java
Color.RED, com.minhaEmpresa.comum.Sexo.MASCULINO
Dezembro de 2006 Hibernate - Uma visão geral sobre o framework padrão De Fato para slide 40 de 78
mapeamento objeto-relacional
HQL – Funcionalidades
Outras funções mais relacionadas com objetos também estão presentes, como operações sobre coleções (o que não
existe no SQL), tais como size().
Também, a partir da homologação do EJB3-QL (que tentou chegar mais perto do OQL), funções específicas desse
padrão estão presentes, como substring(), trim(), etc.
Outra característica do HQL é o suporte direto para qualquer variável estática pública do Java, seja ela da própria API
da linguagem ou definida pelo programador.
40
41. www.3layer.com.br
HQL – Sintaxe
Case insensitive
Suporte a
ORDER BY
GROUP
HAVING
Subqueries (quando o BD suportar)
Junções implícitas pelas associações
Cláusula de junção inferida pelas propriedades
identificadoras (id)
Dezembro de 2006 Hibernate - Uma visão geral sobre o framework padrão De Fato para slide 41 de 78
mapeamento objeto-relacional
HQL – Sintaxe
Quanto a sintaxe, o HQL é case insensitive para as palavras-chaves e funções. Para os tipos de dados (as classes do
usuário) o case é sensitive.
Outras construções presentes no SQL também são suportadas, como ORDER BY, HAVING, etc. Também o suporte a
subqueries (odiada pelos DBA’s) está presente.
Como característica mais saliente do HQL está o suporte a junções de forma implícita. Em outras palavras, ao efetuar
uma junção entre objetos (join) não é necessário especificar quais colunas devem fazer parte dessa junção. Isso é
automaticamente inferido pelo serviço do Hibernate, a partir das estruturas de chaves dos objetos relacionados.
41
42. www.3layer.com.br
HQL – Buscas simples
Nome do
A cláusula pacote da
SELECT é classe
opcional (opcional)
Nome da
classe
from eg.Cat
Retorna um objeto do tipo Cat
from Cat Um alias
from Cat as cat
from Cat cat
Formas equivalentes da primeira consulta
Dezembro de 2006 Hibernate - Uma visão geral sobre o framework padrão De Fato para slide 42 de 78
mapeamento objeto-relacional
HQL – Buscas simples
A partir daquie, vários exemplos são apresentados, em ordem crescente de complexidade.
Nesse exemplo inicial, percebe-se a estrutura da linguagem HQL.
A primeira coisa que se nota é que a clausúla SELECT é opcional. Realmente, ele é opcional quando o tipo retornado é
um (ou vários) objeto(s).
Na claúsula FROM é colocada a origem da consulta. Essa é o nome da classe que deve ter os objetos retornados.
Tanto pode ser o nome simples, como o nome completamente qualificado (prefixado pelos pacotes).
Ainda percebe-se que é possível definir aliases, ou atalhos para essas classes. Isso é importante, uma vez que os
atalhos são usados quando junções devem ser executadas ou mesmo quando das classes devem ser referenciadas
dentro de estruturas como WHERE.
A definição de aliases pode usar ou não a palavra reservada “as”
42
43. www.3layer.com.br
HQL – Mais buscas simples
Inúmeras classes
Uma classe Outra classe podem ser
adicionadas
from Formula, Parameter [,…]
Cria um produto cartesiano entre as classes. Cada linha possui uma
coleção com dois objetos (um Formula e outro Parameter)
from Formula as form, Parameter as param
Mesma coisa, agora com aliases
Dezembro de 2006 Hibernate - Uma visão geral sobre o framework padrão De Fato para slide 43 de 78
mapeamento objeto-relacional
HQL – Mais buscas
Quando várias classes estão presentes na claúsula FROM, um produto cartesiando (MxN) é obtido. Várias classes
podem fazer parte do FROM e, inclusive, podem ou não receber aliases.
43
44. www.3layer.com.br
HQL – Junções
Note o uso do alias
para montagem das
junções
Note que as junções não
especificam cláusulas de
from Pessoa p ligação
inner join p.cidade c
left outer join c.uf
Cria uma junção interna entre uma pessoa e a cidade que ela reside e o
resultado é utilizado em uma junção esquerda com a unidade
federativa da cidade
Dezembro de 2006 Hibernate - Uma visão geral sobre o framework padrão De Fato para slide 44 de 78
mapeamento objeto-relacional
HQL – Junções
As junções são possíveis entre classes relacionadas no modelo de dados. Quando junções são executadas, é
necessário utilizar os aliases na sua montagem, como mostra o exemplo.
As junção padrão é o inner join, embora existam também o full join, o right outer join e o left outer join.
44
45. www.3layer.com.br
HQL – Mais junções
from Pessoa p
inner join p.cidade c Note o uso da claúsula
WHERE sobre uma
left outer join c.uf propriedade de objeto
where c.nome = “Porto Alegre”
Retorna as pessoas que moram na cidade Porto Alegre, quando c.uf não
for igual a null
Dezembro de 2006 Hibernate - Uma visão geral sobre o framework padrão De Fato para slide 45 de 78
mapeamento objeto-relacional
HQL – Mais junções
Nesse exemplo, uma junção é especificada e uma cláusula de seleção (WHERE) adicionada, de forma que somente
parte dos objetos deva ser retornada.
45
46. www.3layer.com.br
HQL – Junções externas
Note o produto
cartesiano para
retornar todas as
cidades
from Pessoa p
inner join p.cidade c
full join c.uf
where c.nome = “Porto Alegre”
Retorna as pessoas que moram na cidade Porto Alegre, mesmo que c.uf
seja igual a null
Dezembro de 2006 Hibernate - Uma visão geral sobre o framework padrão De Fato para slide 46 de 78
mapeamento objeto-relacional
HQL – Junções externas
Aqui um join completo (full join) é usado, para retornar tanto cidades que possuam UFs quanto as que não possuem.
46
47. www.3layer.com.br
HQL – Exemplos simples
Tanto propriedades
Note que o case é simples como
insensitive objetos podem ser
retornados
selECT c.name, c.age, c.mate Note o uso de
From Cat as c variáveis públicas
estáticas
WheRE c.mate.name = “Missy”
(constantes) da API
AND c.color = Color.WHITE do Java
Retorna o nome e a idade do gato, bem como sua companheira quando
esta possuir o nome “Missy” e o pêlo do gato for branco.
Dezembro de 2006 Hibernate - Uma visão geral sobre o framework padrão De Fato para slide 47 de 78
mapeamento objeto-relacional
HQL – Exemplos
Nesse exemplo, percebe-se o uso do case insensitive em qualquer palavra-chave do HQL.
Quanto ao retorno, nota-se que algumas colunas são tipos primitivos (ou seus wrappers), enquanto que outras são
objetos. Isso prova a flexibilidade do HQL.
Também percebe-se o uso de variáveis públicas estáticas (constantes), como Color.WHITE.
47
48. www.3layer.com.br
HQL – Representação em memória
0 1 2
selECT c.name, c.age, c.mate
A mesma
From Cat as c consulta de antes
WheRE c.mate.name = “Missy”
AND c.color = Color.WHITE
O resultado em memória
c.name (String) c.age (int) c.mate (Cat)
Propriedades e
0 Frajola 2 Missy objetos podem
Java.util.List
residir
1 Belo 3 Missy simultaneamente
n … … … no resultado
0 1 2
Java.util.List
Dezembro de 2006 Hibernate - Uma visão geral sobre o framework padrão De Fato para slide 48 de 78
mapeamento objeto-relacional
HQL – Representação em memória dos resultados
Esse exemplo é o mesmo do slide anterior. Ele dá uma idéia de como os dados são armazenados na memória quando
retornados pelo HQL.
Todos os dados retornados pelo HQL são adicionados em objetos do tipo java.util.List. Cada posição dessa lista
também é um objeto do tipo java.util.List. Assim, enquanto algumas posições podem conter tipos simples ou wrappers
(String, boolean, etc.), outras podem conter objetos inteiros (e mesmo complexos, contendo eles mesmo outra
coleções dentro deles).
48
49. www.3layer.com.br
HQL – Forçando o carregamento
mate
Cat
1
mate: Cat
kittens: List<Cat> 2 child Palavra reservada
3 grandchild para inicialização de
kittens coleções
from Cat as cat
1 inner join fetch cat.mate
2 left join fetch cat.kittens child
3 left join fetch child.kittens grandchild
Retorna um gato, inicializando as coleções de seus filhos e netos
Dezembro de 2006 Hibernate - Uma visão geral sobre o framework padrão De Fato para slide 49 de 78
mapeamento objeto-relacional
HQL – Explicitando o carregamento de coleções
No Hibernate, associações podem ter seus objetos inicializados automaticamente ou não. Inicializá-los
automaticamente aumente o overhead do sistema, mas diminui o esforço de programação.
Quando as associações não são inicializadas automaticamente, pode-se lançar mão da palavra reservada “fetch”. Ela
sinaliza o serviço do Hibernate para ele inicializar a associação, mesmo que inicialmente ela não tenha sido projetada
para ser inicializada durante o carregamento do objeto pai.
Nesse exemplo percebe-se claramente o uso do alias como forma de executar um auto-relacionamento, buscando
dados em segundo nível na estrutura.
Aqui, Cat é uma tabela que armazena o nome do gato e sea companheira (esposa) através do auto-relacionamento
“mate”. Fetch é usado na primeira junção porque mate não é inicializado automaticamente quando o gato é carregado.
Depois de carregado o gato e sua mate, uma junção é feita para encontrar seus filhos (kittens). Como é desejado usar
esses filhos em outra junção, é usado um alias “child” para ela. Esse resultado é cruzado novamente com kittens, de
forma a obter os netos do gato original. Como são junções esquerdas (left joins), somente registros que não
contenham NULL serão retornados. Em outras palavras, a seleção acima somente retorna os gatos que possuem uma
mate (esposa) e que tenham filhos que possuam outros filhos.
49
50. www.3layer.com.br
HQL – Herança
Herança
Query polimórfica (herança)
SerVivo
from SerVivo
Retorna todos seres vivos, animais e vejetais
from Animal Animal Vegetal
Retorna somente seres vivos do tipo Animal
from Vegetal as v
Retorna somente seres vivos do tipo Vegetal
Dezembro de 2006 Hibernate - Uma visão geral sobre o framework padrão De Fato para slide 50 de 78
mapeamento objeto-relacional
HQL e Herança
Quanto à herança, o HQL é muito prático.
Dada a estrutura à direita do slide, buscas sobre toda a estrutrua ou somente parte dela podem ser executadas.
50
51. www.3layer.com.br
HQL – Herança e SQL
O SQL gerado depende da Estrutrura OO
implementanção usada na herança,
podendo ser: SerVivo
HQL:
from Animal
Animal Vegetal
SQL:
select sv.id, sv.nome, a.temp
from serVivo sv inner join Estrutrura relacional
animal a on sv.id = a.id
SerVivo
Id
nome
Um possível Animal
mapeamento, Id
Id <FK>
table per subclass temperatura
Dezembro de 2006 Hibernate - Uma visão geral sobre o framework padrão De Fato para slide 51 de 78
mapeamento objeto-relacional
HQL e SQL
No tocante ao que ocorre quando uma consulta que utiliza estruturas com herança é executada, esse slide mostra um
possível mapeamento para o SQL.
Como muitas abordagens podem ser usadas para mapear estrutruras de herança em modelos relacionais, somente
uma delas é mostrada. Acima está a estrutura OO com herança e o respectivo mapeamento relacional utilizado. A
consulta HQL executada e o respectivo SQL gerado são mostrados.
51
52. www.3layer.com.br
HQL – Coleções
SELECT p.nome, p.fones
FROM Pessoa p join p.fones f
WHERE f.codArea = 51
AND size(p.fones) > 3
Seleciona o nome e os telefones da pessoa quando o código de área do
telefone for 51 e a pessoa possuir mais de 3 telefones
from Cat cat
where exists elements(cat.kittens)
from Player p
where 3 > all elements(p.scores)
Usando funções
sobre coleções
Dezembro de 2006 Hibernate - Uma visão geral sobre o framework padrão De Fato para slide 52 de 78
mapeamento objeto-relacional
HQL e Coleções
Quanto a operações sobre coleções, a HQL é generosa. Inúmeras possibilidades, expressões e construções podem ser
feitas.
Nesse exemplo estão algumas aplicações de funções sobre coleções, como o size() e o uso de operadores como o
“exists” e o “all”. Percebe-se que a própria estrutura da linguagem dispensa comentários sobre o que está sendo
buscado com os comandos.
52