Hibernate

Propaganda
Criando e executando consultas
Formas de criar consultas
1
Formas de consultas
• Hibernate Query Language (HQL), e um subconjunto do
padrão JPA QL (Java Persistence API Query Language :
session.createQuery("from Category c where c.name like 'Laptop%'");
entityManager.createQuery("select c from Category c where c.name like
'Laptop%'“ );
• Criteria API para consulta por critério (QBC) e consulta por
exemplo (QBE):
session.createCriteria(Category.class).add( Restrictions.like("name",
"Laptop%") );
• SQL direto com ou sem mapeamento automático do
resultsets para objeto.
session.createSQLQuery( "select {c.*} from CATEGORY {c} where
NAME like 'Laptop%'").addEntity("c", Category.class);
2
Preparando uma consulta
• As interfaces org.hibernate.Query e
org.hibernate.Criteria possuem inúmeros métodos
para controlar a execução de uma consulta.
• Query provê métodos para atribuir valores para
parâmetros de consulta.
• Para executar uma consulta em uma aplicação é
necessário obter uma instância de uma destas
interfaces utilizando a Session.
Query hqlQuery =
session.createQuery("from Event");
3
Associação <one-to-many>
• Uma associação <um-para-muitos> liga as tabelas
de duas classes através de uma chave estrangeira
sem intervensão nas tabelas.
• Este mapeamento perde certa semântica para uma
coleção normal Java:
– Uma instância que contem uma classe entidade não pode
pertencer a mais de uma instância de coleção.
– Uma instância que contem uma classe entidade não pode
aparecer em mais de um valor de um índice de coleção.
• Uma associação de Estados e Municípios requer a
existência de uma coluna de chave estrangeira e a
possibilidade de uma coluna índice para a tabela
Municípios.
4
<one-to-many
class="ClassName"
not-found="ignore|exception"
entity-name="EntityName"
node="element-name"
embed-xml="true|false"
/>
• class (obrigatório): O nome da classe associada
• not-found (opcional): Especifica como colocar em cache
identificadores que referenciam as linhas inexistentes devem
ser manipuladas. ignore tratará uma linha inexistente como
uma associação nula.
• entity-name (opcional): O nome da entidade classe
associada, como uma classe alternativa.
5
Exemplo
<hibernate-mapping>
<class name="exemploestadolista.Estado"
table="Estados">
<id name="ibge" column="IBGE">
</id>
<property name="sigla"/>
<property name="nome"/>
<property name="area"/>
<set name="municipios" table="municipios">
<key column="uf"/>
<one-to-many
class="exemploestadolista.Municipio"
/>
</set>
</class>
</hibernate-mapping>
6
Limitando a quantidade de respostas
Query consulta =
session.createQuery("from Estado order
by sigla asc");
consulta.setMaxResults(10);
Apresenta um conjunto com 10 elementos
7
Utiliza SQL e limitador
Query consulta =
session.createSQLQuery("select {e.*}
from estados {e} order by {e.sigla}").
addEntity("e",Estado.class);
consulta.setFirstResult(5);
consulta.setMaxResults(10);
Utiliza expressão SQL. Inicia o resultado no quinto
elemento e apresenta 10 registros.
8
Utiliza Criteria
Query consulta =
session
.createQuery(" from Estado order by sigla
asc").setMaxResults(10);
Criteria crit =
session.createCriteria(Estado.class)
.addOrder(Order.desc("sigla"))
.setFirstResult(5)
.setMaxResults(6);
List relEstados = crit.list();
9
Consulta com parâmetro
String consultaString =
"from Estado uf where uf.sigla = :pesquisa";
String ufString = "PR";
Query consulta =
session.createQuery(consultaString).setString
("pesquisa", ufString);
10
HQL Hibernate Query Language
Caio Nakashima
[email protected]
[email protected]
11
HQL
• Hibernate é equipado com uma linguagem de consulta
extremamente poderosa que (intencionalmente) é muito
parecida com SQL.
• HQL é completamente orientado a objetos, entendendo
noções como herança, polifomorfismo e associação.
• Consultas são case-insensitive (não sensíveis à letra), com
exceção de nomes para as classes e propriedades Java.
• Assim SeleCT tem o mesmo significado que sELEct e
SELECT mas org.hibernate.eg.FOO não é igual a
org.hibernate.eg.Foo e foo.barSet não é igual a not
foo.BARSET.
12
Cláusula FROM
• A mais simples consulta Hibernate é:
from eg.Cat
• Que retorna todas as instâncias da classe Cat. Não
é necessário qualificar o nome da classe, desde que
a auto importação é o padrão. Assim geralmente
escreve-se:
from Cat
• Muitas vezes, é necessário atribuir uma alias, desde
que deseja-se referir ao Cat em outras partes da
consulta.
from Cat as cat
13
Cláusula FROM (2)
• Esta consulta atribui para a instância Cat um alias cat, assim
pode-se utiliza-lo em outras partes da expressão de
consulta. A palavra chave AS é opcional, assim pode-se
escrever também:
from Cat cat
• Pode-se utilizar múltiplas classes, resultando um produto
cartesiano ou um "cross" join.
from Formula, Parameter
from Formula as form, Parameter as param
• É considerado uma boa prática nomear alias de consulta
utilizando a primeira letra em minúscula, sendo consistente
com o padrão Java para nomear variáveis locais.
14
Associações e Junções
• Pode-se também associar aliases para entidades
associadas ou também para elementos de uma
coleção de valores utilizando JOIN.
• from Cat as cat
inner join cat.mate as mate
left outer join cat.kittens as kitten
• from Cat as cat left join
cat.mate.kittens as kittens
• from Formula form full join
form.parameter param
15
Associações e Junções
• Os tipos de junções (joins) suportados são
emprestados do SQL ANSI:
–
–
–
–
inner join
left outer join
right outer join
full join
• As construções inner join, left outer join e right
outer join podem ser abreviadas.
from Cat as cat
join cat.mate as mate
left join cat.kittens as kitten
16
Fetching strategies
• Em um acesso tradicional aos dados, pode-se pegar
todos dos dados requeridos para um processo em
particular para uma consulta SQL simples, contando
com a vantagem de junções internas ou externas
(inner or outer joins) para recuperar as entidades
relacionadas.
• Algumas primitivas implementadas no modelo ORM
(object/relational mapping) para pegar "pedaços"
de dados com inúmeras requisições para pequenos
pedaços de dados em resposta das aplicações
navegando um grafo de objetos persistentes, não é
uma forma eficiente de utilização das capacidades
de junção (join) do banco de dados.
17
• Esta estratégia de acesso a dados é pobre por
natureza.
• Uma das maiores dificuldades em ORM é prover um
acesso eficiente para os dados relacionais, dando
uma aplicação que prefere tratar os dados como um
objeto de grafo.
• Para os tipos mais comuns de aplicações (multiusuário, distribuído, web e aplicações
coorporativas), a recuperação de objetos utilizando
muitos acessos ao banco de dados não é aceitável.
Será discutido que as ferramentas devem enfatizar
o R em ORM para a extensão maior que a
tradicional.
18
• O problema de pegar objetos de grafos eficientemente, com
acesso mínimo para o banco de dados, tem freqüentemente
associando com o provimento ao nível de associação da
estratégia de capturar um meta dados específico do
mapeamento de associação.
• O problema com esta solução é que cada pedaço do código
que utiliza um requisito de entidade um conjunto diferente de
objetos associados. Mas isto não é suficiente.
• É necessário um suporte para refino da estratégia de
execução da associação de captura.
• Hibernate suporta as duas estratégias, que permite
especificar uma estratégia padrão de captura no arquivo de
mapeamento e então sobre escrever em tempo de execução
no código.
19
• Hibernate permite escolher entre quarto estratégia
de captura para qualquer associação, nos
metadados de associação e em tempo de
execução:
• Immediate fetching - Captura Imediata
– O objeto associado é capturado imediatamente, utilizando
uma leitura em banco de dados seqüencial (cache).
• Lazy fetching - Captura preguiçosa
– O objeto associado ou coleção é capturado de "forma
preguiçosa", quando é acessado. Resultada é uma nova
requisição para o banco de dados (a não ser que o objeto
associado esteja no cache).
20
• Eager fetching - Captura urgente
– Um objeto associado ou coleção é capturado junto com o
objeto proprietário, utilizando um outer join SQL, e
nenhum outra requisição ao banco de dados é requerida.
• Batch fetching - Captura em Lote
– Esta abordagem pode ser utilizada para melhorar a
performance da captura "preguiçosa" recuperando objetos
ou coleções em lote, quando uma uma associação
"preguiçosa" é acessada.
– Captura em lote pode ser utilizado para melhorar a
performance da captura imediata.
21
Immediate fetching (captura imediata)
• Captura associativa imediata ocorre para recuperar
uma entidade do banco de dados e então recuperar
imediatamente outra entidade associada ou
entidades em uma requisição futura do banco de
dados ou do cache.
• Captura imediata não é uma estratégia captura
eficiente a não ser que espere que as entidades
associadas estejam quase sempre no cache.
22
Lazy fetching (captura preguiçosa)
• Quando um cliente requisita uma entidade e seu
grafo de objetos associdado do banco de dados,
não é usualmente necessário recuperar todo o grafo
de todos os objetos associados (indiretamente).
• Não se deseja carregar todo o banco de dados para
a memória de uma vez, por exemplo, carregar um
Pedido simples, não deve disparar uma carga de
todos os itens do pedido.
• Lazy fetching permite ao programador decidir
quantos grafos de objetos serão carregados no
primeiro acesso ao banco de dados e quais
associações devem ser carregadas somente
quando forem acessadas pela primeira vez.
23
Lazy fetching (cont.)
• Lazy fetching é um conceito fundamental em
persistência de objetos e o primeiro passo para
obter uma performance aceitável.
• Recomenda-se que, para começar com todas as
associações sejam configurados para lazy ou talvez
para batched lazy carregamento no arquivo de
mapeamento.
• Esta estratégia pode ser carregada (definida) em
tempo de execução por consultas que forçam uma
carga urgente.
24
Eager (outer join) fetching
• Carga associada preguiçosa pode ajudar a reduzir a
carga no banco de dados e é geralmente uma boa
estratégia padrão.
• Porém, é algo parecido como um "chute no escuro"
assim como uma otimização de performance.
• Carga urgente permite explicitamente especificar
qual objeto associado deve ser carregado junto com
o objeto referenciado.
• Hibernate pode então retornar o objeto associado
em uma requisição simples no banco de dados,
utilizando um SQL OUTER JOIN.
25
Eager (outer join) fetching
• Otimização de performance no Hibernate
geralmente envolve um uso discreto da carga
urgente para uma transação em particular.
• Desta forma, mesmo que padrão a carga urgente
pode ser declarada no arquivo de mapeamento, é
mais comum para uma utilização específica desta
estratégia em tempo de execução para uma HQL
particular ou critério de consulta.
26
Batch fetching
• Carga em lote não é estritamente uma estratégia de carga
associada; é uma técnica que pode ajudar a melhorar a
performance da carga preguiçosa ou carga imediata.
• Geralmente, quando se carrega um objeto ou uma coleção, a
cláusula WHERE do SQL especifica o identificador do objeto
ou os objetos que possuem a coleção.
• Se a carga em lote estiver habilitada, Hibernate procura ver o
que outras instâncias de proxie ou coleções não inicializadas
são referenciadas na seção corrente e tenta carrega-los ao
mesmo tempo especificando múltiplos valores identificadores
na clásula WHERE.
27
• Carga urgente é geralmente mais rápida.
• Carga em batch é mais fácila para os usuários
inexperientes que desejam arquivar com uma
performance aceitável com Hibernate sem ter que
pensar muito sobre o que SQL executará.
28
Selecionando uma estratégia de carga no
mapeamento
• Hibernate permite selecionar associação padrão
para estratégia de carga especificando atributos nos
metadados de mapeamento.
• Pode-se carregar uma estratégia padrão utilizando
características de consulta do Hibernate.
• A wrinkle in Hibernate’s mapping format means that
collection mappings function slightly differently than
single-point associations; so, we’ll cover the two
cases separately.
• Let’s first consider both ends of the bidirectional
association between Bid and Item.
29
• Uma junção "fetch" permite associações ou
coleções de valores serem inicializadas por seus
objetos pai, utilizando uma seleção simples.
• É útil particularmente em caso de uma coleção
(collection).
• É eficiente para sobre escrever um outer join e lazy
declarations do arquivo de mapeamento para
associações e coleções.
from Cat as cat
inner join fetch cat.mate
left join fetch cat.kittens
30
• Um fetch join geralmente não necessita atribuir um
alias, por que os objetos associados não deve ser
utilizado na cláusula where ou qualquer outra
cláusula.
• Objetos associados não retornam diretamente em
resultados de uma consulta.
• Por outro lado, podem ser acessados por objetos
pai.
• A única razão que se necessita um alias se existir
um join fetching recursivo para uma coleção futura.
31
from Cat as cat
inner join fetch cat.mate
left join fetch cat.kittens child
left join fetch child.kittens
• Prestar atenção que uma construção com fetch não
deve ser utilizado com consultas chamadas
utilizando scroll() ou iterate().
• Nem o fetch pode ser utilizado junto com
setMaxResults() ou setFirstResult().
32
Produto Cartesiano
• É possível criar um produto cartesiano juntando
mais de uma coleção de em uma consulta, assim
deve-se tomar cuidado neste caso.
– Juntando múltiplas coleções pode resultar em resultados
inesperados de um mapeamento mal feito.
• Se utilizar a propriedade lazy fetching com a
instrumentalização bytecode, é possível forçar o
Hibernate a percorrer a propriedade lazy
imediatamente na primeira consulta utilizando todas
as propriedades de navegação.
from Document fetch all properties order by
name
from Document doc fetch all properties where
lower(doc.name) like '%cats%'
33
Download