Hibernate PowerPoint PPT Presentation

presentation player overlay
1 / 59
About This Presentation
Transcript and Presenter's Notes

Title: Hibernate


1
Hibernate conceitos e consultas
  • Jobson Ronan jrjs_at_cin.ufpe.br

2
Objetivos
  • Aprender sobre os conceitos de persistência
    relacionados ao Hibernate
  • Aprender como recuperar os dados e efetuar
    consultas de maneira eficientemente no Hibernate

3
Ciclo de vida da persistência
  • Como Hibernate oferece um sistema transparente de
    persistência, as classes não sabem de sua
    capacidade de persistência
  • Por outro lado, a aplicação que usa os objetos,
    os utiliza em estados diferentes
  • Transientes, antes de serem gravados em meio
    persistente
  • Persistentes, quando estão armazenados
  • Desligados, quando suas instâncias são
    manipuladas sem afetar a base de dados

4
Diagrama de estados
5
Objetos transientes
  • Objetos que acabaram de ser criados (com new)
    ainda não são persistentes
  • Seu estado é transiente (ainda não foram
    armazenados no banco e deixarão de existir assim
    que perderem sua referência)
  • Session.delete() sobre um objeto persistente
    torna-o transiente
  • Instâncias transientes são não-transacionais
  • Rollback não recupera seu estado anterior
  • Objetos referenciados por instâncias transientes
    são (por default) também transientes
  • Para mudar para o estado persistente é preciso
  • Passar o objeto como argumento de um
    Session.save(), ou
  • Criar a referência a partir de uma instância
    persistente

6
Objetos persistentes
  • Uma instância persistente é uma instância com uma
    identidade no banco de dados
  • Tem uma chave primária como identificador
  • Podem ser
  • Objeto criado com new e armazenado com
    Session.save()
  • Objeto criado a partir da referência de uma
    instância persistente
  • Objeto obtido a partir de um query no banco
  • Estão sempre associados com uma Session
  • São transacionais
  • Seu estado é sincronizado com o banco ao fim da
    transação
  • Automatic dirty checking (transparente ao
    usuário) é usado como estratégia de atualização
    eficiente de dados

7
Objetos desligados (detached)
  • Quando a sessão é fechada (Session.close()) todas
    as instâncias ainda mantém seu estado, mas não
    estão mais sincronizadas com o banco
  • Podem ficar obsoletas se houver mudança no banco
  • Podem mudar de estado, que não será refletido no
    banco
  • Mas, a qualquer momento, a sessão pode ser
    reativada, tornando o objeto persistente e
    sincronizando seu estado
  • Objetos desligados são úteis para transportar o
    estado de objetos persistentes para outras
    camadas
  • Camada de apresentação, em substituição aos DTOs
    (Data Transfer Objects, também chamados de Value
    Objects)

8
Como tornar um objeto persistente
  • 1) Crie o objeto e inicialize suas propriedades
  • User user new User()
  • user.getName().setFirstname("John")
  • user.getName().setLastname("Doe")
  • 2) Abra uma sessão
  • Session session factory.openSession()
  • 3) Inicie uma transação
  • Transaction tx session.beginTransaction()
  • 4) Grave o objeto
  • session.save(user)
  • 5) Cometa a transação
  • tx.commit()
  • 6) Feche a sessão
  • session.close()

9
Como atualizar estado de instâncias desligadas
  • Quando a sessão for fechada, user torna-se uma
    instância desligada
  • Qualquer alteração no seu estado não afeta o
    banco
  • Para religá-lo pode-se usar update()

user.setPassword("secret") // objeto
desligado Session sessionTwo sessions.openSessio
n() Transaction tx sessionTwo.beginTransaction(
) sessionTwo.update(user) user.setUsername("jonn
y") // objeto persistente tx.commit() sessionTwo
.close()
10
Como recuperar um objeto persistente
  • A forma mais simples de recuperar um objeto é
    pelo identificador, usando o comando get()
  • Uma vez que a sessão foi fechada, o objeto é uma
    instância desligada, e pode ser repassada para
    outras camadas (apresentação, por exemplo)
  • Se o objeto não existir, a chamada get() retorna
    null

Session session sessions.openSession()
Transaction tx session.beginTransaction()
int userID 1234 User user (User)
session.get(User.class, new Long(userID))
tx.commit() session.close()
11
Como atualizar um objeto persistente
  • Qualquer objeto retornado por get() é um objeto
    persistente
  • Quaisquer modificações no seu estado serão
    sincronizadas com o banco de dados
  • Hibernate automaticamente verifica e grava as
    mudanças ocorridas dentro de uma sessão
    (automatic dirty checking)
  • As mudanças tornam-se permanentes ao cometer a
    transação
  • O objeto torna-se desligado quando a sessão fecha

Session session sessions.openSession() Transact
ion tx session.beginTransaction() int userID
1234 User user (User) session.get(User.class,
new Long(userID)) user.setPassword("secret") tx.
commit() session.close()
12
Como tornar transiente um objeto persistente
  • Um objeto persistente pode tornar-se transiente
    se for removido do banco
  • Para isto é preciso usar o gerente de
    persistência e chamar o método delete()
  • Quando a sessão terminar o objeto será
    considerado um mero objeto Java transiente (cujo
    estado será perdido assim que o coletor de lixo
    atuar)

Session session sessions.openSession() Transact
ion tx session.beginTransaction() int userID
1234 User user (User) session.get(User.class,
new Long(userID)) session.delete(user) tx.commit
() session.close()
13
Como tornar transiente um objeto desligado
  • Para tornar um objeto desligado transiente, não é
    preciso ligá-lo ou fazer update()
  • Basta chamar delete() sobre sua instância

Session session sessions.openSession() Transact
ion tx session.beginTransaction() session.delet
e(user) tx.commit() session.close()
14
API Session ciclo de vida (Resumida)
  • beginTransaction()
  • Demarca o início de uma transação. Retorna um
    objeto Transaction que deve chamar commit() ou
    rollback() no final da transação.
  • close()
  • Fecha e desconecta a sessão
  • disconnect()
  • Desconecta a sessão da conexão JDBC atual sem
    fechá-la.
  • reconnect()
  • Obtém uma nova conexão JDBC para a sessão ou
    tenta conectar a uma conexão JDBC, se passada
    como argumento
  • flush()
  • Sincroniza a camada de objetos com a camada de
    dados. Este método é chamado automaticamente
    quando a transação é cometida.

15
Session gerência de persistência (Resumida)
  • save(Object)
  • Torna persistente o objeto passado como argumento
  • saveOrUpdate(Object)
  • Insere (tornando persistente) ou atualiza o
    objeto passado como argumento
  • update(Object)
  • Atualiza o objeto passado como argumento
  • delete(Object instancia)
  • Remove os dados de um objeto do banco, tornando-o
    transiente
  • load(classe, identificador)
  • Carrega e retorna a instância de objeto
    identificado pela classe e identificador
  • refresh(Object)
  • Recarrega do banco os dados da instância passada
    como argumento
  • evict(Object)
  • Remove o objeto passado como argumento do cache
    do sistema

16
Recuperação de dados
  • Formas de recuperar objetos
  • Pelo identificador
  • Navegando na árvore de objetos ex
    usuario.getEndereco().getCidade()
  • Usando HQL
  • Usando a API Criteria
  • Usando SQL nativo

17
Recuperação por identificador
  • Há dois métodos de Session para recuperar objetos
    pelo identificador
  • Ambos utilizam o cache, e evitam acessar o banco
    se não for necessário
  • Object get(Object id)
  • Devolve o objeto se existir e null se o objeto
    não for encontrado no banco ou no cache
  • Object load(Object id)
  • Devolve o objeto ou um proxy para o objeto se
    existirem, ou causa exceção se nenhum for
    encontrado no banco ou no cache
  • O proxy pode apontar para objeto que ainda ou não
    mais existe

18
HQL
  • Hibernate Query Language é um dialeto orientado a
    objetos do SQL
  • Assemelha-se a ODMG OQL e EJB-QL mas é adaptado
    para uso em bancos de dados SQL
  • Não é uma linguagem de manipulação de dados (como
    SQL) não serve para inserir, remover, atualizar
  • É usada apenas para recuperação de objetos
  • Exemplo

Query q session.createQuery("from User u
where u.firstname fname") q.setString("fname",
"Max") List result q.list()
19
HQL
  • HQL suporta vários recursos úteis e avançados
    entre eles
  • Pesquisas com navegação do grafo de objetos
  • Recuperação seletiva de propriedades dos objetos
    selecionados (sem ter que carregar objeto
    inteiro)
  • Ordenação de resultados
  • Paginação de resultados
  • Agregação com group by, having, e funções sobre
    agregados como sum, count, min e max
  • Outer joins ao recuperar múltiplos objetos por
    registro
  • Chamadas a funções SQL definidas pelo usuário
  • Subqueries

20
Consulta usando Criteria (QBC)
  • QBC Query By Criteria
  • Queries podem ser expressos usando uma API em vez
    de usar HQL
  • Evita uso de strings
  • Validação é feita em tempo de compilação
  • Enfoque mais orientado a objetos
  • Mais difícil de ler (é Java e não HQL)
  • Exemplo
  • Em HQL from User u where u.firstname fname
  • Em QBC

Criteria criteria session.createCriteria(User.cl
ass) criteria.add( Expression.like("firstname",
"Max") ) List result criteria.list()
21
Como achar os dados?
  • Talvez o problema mais difícil de solucionar em
    ORM acesso eficiente a dados relacionais
  • Aplicação prefere tratar os dados como um grafo
    de objetos interligados por associações
  • É mais fácil é fazer vários pequenos queries
    (performance baixa)
  • Alternativa escrever queries para cada
    associação (muito complexo e pouco flexível)
  • Hibernate permite especificar uma estratégia de
    recuperação default (no mapeamento) que pode ser
    sobreposta em tempo de execução

22
Estratégias de recuperação
  • Fetching strategies
  • Estratégias para qualquer associação (nos
    metadados e em tempo de execução)
  • Lazy fetching objeto associado só é recuperado
    quando chamado
  • Eager fetching objeto associado é recuperado
    através de SQL outer join
  • Batch fetching acessa uma coleção de objetos
    pré-determinada

23
Lazy fetching
  • Permite que apenas parte do grafo de objetos seja
    carregado inicialmente
  • O restante do grafo pode ser carregado à medida
    em que for necessário
  • Vai requer mais chamadas ao banco posteriormente,
    mas pode ser que elas não sejam necessárias
  • Pode ser otimizada com Batch Fetching
  • Deve ser a estratégia inicial para todas as
    associações no arquivo de mapeamento
  • A estratégia pode depois ser sobreposta em tempo
    de execução por estratégias mais ávidas

24
LazyInitializationException
  • Erro comum, causado por inicialização lazy
  • A forma mais simples de evitá-lo, é realizar tudo
    dentro da sessão (o commit() sincroniza os dados
    e evita a inconsistência)
  • Sabendo-se do estado do objeto, os dados podem
    ser recuperados em outra sessão (quando voltar a
    ser persistente)

s sessions.openSession() User u (User)
s.createQuery("from User u where
u.name?).setString(userName).list().get(0) Map
permissions u.getPermissions() s.connection().c
ommit() s.close() Integer accessLevel
(Integer) permissions.get("accounts") // Error!
25
Recuperação em lote (Batch fetching)
  • Na verdade não é uma outra estratégia
  • É uma solução rápida para otimizar lazy fetching
  • É um lazy menos lazy usuário define quantos
    níveis de associações devem ser carregadas
  • Hibernate procura as outras instâncias associadas
    à coleção e tenta carregá-las ao mesmo tempo
  • Pode ser melhor que lazy simples
  • Menos chamadas ao banco

26
Eager fetching
  • É uma solução que ajuda a reduzir a carga sobre o
    banco de dados de forma mais inteligente que
    Batch Fetching
  • Pode ser um a boa estratégia default
  • Permite que se especifique explicitamente quais
    objetos associados devem ser carregados juntos
    com o objeto que os referencia
  • Os objetos associados podem então ser retornados
    em única requisição
  • Usa SQL outer join
  • Otimização de performance em Hibernate
    freqüentemente usa esse tipo de estratégia em
    tempo de execução para um query em particular

27
Qual estratégia usar?
  • A seleção de uma estratégia de recuperação de
    dados default é feita através de atributos no XML
    do arquivo de mapeamento.
  • Mapeamentos de coleção diferem dependendo do tipo
    de associações.
  • Coleções e associações de muitos para muitos
    comportam-se diferentemente de associações
    singulares -to-one.

28
outer-join em associações -to-one
  • O atributo outer-join sobrepõe lazy fetching
  • Usado do lado oposto da associação
  • O outro lado escolhe lazy fetching (ou immediate
    fetching por omissão)
  • Opções
  • outer-joinauto (default). O comportamento é
    lazy, se o outro lado (singular) da associação
    especificar, ou eager, se não especificado.
  • outer-jointrue Comportamento é sempre eager
    para esta associação (logo diferentes associações
    para mesmo objeto podem ter estratégias
    diferentes)
  • outer-joinfalse Se o objeto tiver sido
    mapeado como lazy, ocorre lazy fetching, caso
    contrário, immediate fetching (SQL select)
  • Exemplo
  • ltmany-to-one name"item" class"Item"
    outer-join"true"gt

29
Em coleções
  • Lazy
  • Use atributo lazytrue (não depende de proxy do
    outro lado)
  • ltset name"bids" lazy"true"gt
  • Batched Lazy
  • Acrescente o atributo batch-sizetamanho
    (refere-se ao número de coleções
  • ltset name"bids" lazy"true" batch-size"9"gt
  • Eager
  • Use atributo outer-jointrue
  • Evite usar como opção default

30
Consultas HQL
  • O query mais simples possível
  • Os resultados de um query podem ser lidos em
    páginas
  • O query abaixo lê 10 páginas, a partir da
    primeira página
  • Listagem de resultados

Query q1 session.createQuery("from User")
Query query session.createQuery("from User u
order by u.name asc")query.setFirstResult(0)qu
ery.setMaxResults(10)List results
query.list()
List result session.createQuery("from
User").list()
31
Passagem de parâmetros
  • Evite montar queries via concatenação de strings
  • Risco de segurança basta esquecer de fechar a
    aspa
  • Longos queries ficam ilegíveis
  • O ideal é passar parâmetros que serão ligados ao
    query
  • Parâmetros podem ser passados duas formas
  • Por nome de variável
  • Por ordem (como PreparedStatement em java.sql)

32
Passagem de parâmetros
  • Parâmetros passados por nome
  • No query, o nome deve ser precedido de um
  • Parâmetros por posição

String queryString "from Item item where
item.description like searchString"
String queryString "from Item item " "where
item.description like ? " "and item.date gt
?" List result session.createQuery(queryString)
.setString(0, searchString)
.setDate(1, minDate) .list()
33
Queries chamados pelo nome
  • Queries não precisam aparecer no código
  • Na verdade, muitas vezes é melhor que não
    apareçam
  • Podem ficar nos metadados e serem chamados pelo
    nome
  • Para chamar um query pelo nome, use
    getNamedQuery()
  • Mas antes, é preciso que ele seja declarado em
    algum arquivo de mapeamento (ex Item.hbm.xml)

List result session.getNamedQuery("findItemsByDe
scription") .setString("description",
description).list()
ltquery name"findItemsByDescription"gtlt!CDATA fr
om Item item where item.description like
description gtlt/querygt
34
Aliases
  • Aliases (apelidos) são usados para que se possa
    ter uma referência para acessar propriedades das
    instâncias recuperadas
  • from Livro
  • é suficiente para recuperar todos os livros
  • Um alias é declarado da seguinte forma
  • from Livro as livro
  • Mas o as é opcional
  • from Livro livro
  • Exemplo para testar as propriedades em um where
  • from Livro livrowhere livro.codigo 005.133

35
Queries polimórficos
  • Considere a hierarquia ao lado
  • O query abaixo é polimórfico
  • from BillingDetails
  • pois os resultados são classes concretas
    BankAccount e CreditCard
  • Queries polimórficos podem ser feitos em qualquer
    classe, não apenas em classes mapeadas
  • O query abaixo retorna todas as instâncias
    mapeadas
  • from java.lang.Object
  • Criteria também suporta polimorfismo
  • List res session.createCriteria(java.lang.Ob
    ject.class) .list()

36
Mais HQL Restrições (where)
  • Como em SQL, HQL define restrições de um query
    através da cláusula where, que suporta várias
    expressões.
  • Por exemplo, a expressão de equivalência
  • from User u where u.email 'foo_at_hibernate.org
  • A expressão where pode ter resultado true, false
    ou null
  • lógica ternária
  • HQL suporta os mesmos operadores que SQL
  • Queries Criteria expressões na classe Expression
  • Não há suporte para expressões aritméticas via
    API (só via HQL)
  • Operadores do HQL
  • Comparação , ltgt, lt, gt, gt, lt, between, not
    between, in, not in
  • Nulidade is null, is not null
  • Aritméticos , -, /, , , parênteses

37
Mais HQL Restrições (where)
  • Exemplos

from Bid bid where bid.amount between 1 and
10 from Bid bid where bid.amount gt 100 from User
u where u.email in ( "foo_at_abc.org", "bar_at_abc.org"
) from User u where u.email is null from Bid bid
where ( bid.amount / 0.71 ) - 100.0 gt 0.0
38
Mais HQL strings
  • O operador like funciona da mesma forma que SQL
  • O símbolo _ representa um caractere
  • O símbolo representa vários caracteres
  • Exemplos
  • HQL from User u where u.firstname like "G"
  • Criteria session.createCriteria(User.class)
    .add(Expression.like("firstname","G"))
  • Pode-se usar funções SQL se banco suportar
  • from User u where lower(u.email) 'foo_at_abc.org'
  • Não há um operador padrão de concatenação de
    strings
  • É preciso usar recursos do banco nativo.
  • Exemplo where (u.fname ' ' u.lname) like
    'G K'

39
Mais HQL
  • Operadores lógicos and, or, parênteses, etc.
    servem para argupar expressões
  • Ordenação Semelhante a SQL order by
  • asc ascendente (default)
  • desc descendente

from User user where ( user.firstname like "G"
and user.lastname like "K" ) or
user.email in ( "foo_at_abc.org", "bar_at_abc.org"
)
from User u order by u.lname asc, u.fname asc
40
  • ...Pensou que acabou?

41
Joins
  • Joins (junções) são usados para combinar dados de
    duas ou mais tabelas relacionadas
  • Há quatro tipos de joins possíveis
  • Inner join
  • Left outer join
  • Right outer join
  • Full join
  • Além disso, há dois estilos em SQL
  • ANSI junção de tabelas através de propriedade
    comum com condição de join na cláusula on
  • Theta produto cartesiano de tabelas com condição
    de join na cláusula where
  • Joins em HQL são bem mais simples que em SQL

42
SQL ANSI inner join e left outer join
  • Inner join (ou simplesmente join) -
    apenas Itens com Bids
  • Left outer join (ou left join) - Inclui
    também Itens que não têm Bids
  • Right outer join (right join) - permite valores
    nulos na tabela esquerda (inclui Bids sem Itens
    mas não itens sem Bids) não faz sentido neste
    caso (lance sem item)
  • Full join - permite valores nulos nas duas
    tabelas (inclui Bids que não têm Itens e itens
    que não têm Bids) também não faz sentido neste
    caso

43
Joins em HQL
  • Em Hibernate, geralmente condições de join não
    são especificadas explicitamente
  • Elas podem ser deduzidas das associações entre
    objetos automaticamente
  • Queries ficam mais simples e legíveis
  • Quatro maneiras de expressar joins em HQL
  • Fetch join (outer, agressivo) na cláusula from
  • Join comum (inner, lazy) na cláusula from
  • Join theta-style (produto cartesiano) na cláusula
    where
  • Join por associação explícita

44
Fetch join
  • Recupera objeto inteiro (com associações
    inicializadas.)
  • Exemplo HQL
  • from Item item left join fetch item.bids
    where item.description like 'gc

Retorna lista de objetos com coleções já
inicializadas
45
Join simples (inner) com alias
  • Freqüentemente é necessário aplicar restrições a
    tabelas combinadas com join.
  • Isto pode ser feito atribuíndo um alias ao join
  • from Item item join item.bids bid where
    item.description like 'gc and bid.amount
    gt 100
  • O query acima é um inner join
  • Em vez de uma lista de Item, retorna uma lista de
    Object
  • Retorna uma lista de arrays item, bid (Se fosse
    um fetch join, retornaria uma lista de Item com
    coleção de bids inicializada)
  • Um Item pode aparecer múltiplas vezes (uma vez
    para cada Bid associado)

46
inner join x outer (fetch) join
Como obter os dados usando um inner join
Query q session.createQuery("from Item item
join item.bids bid") Iterator pairs
q.list().iterator() while ( pairs.hasNext() )
Object pair (Object) pairs.next()
Item item (Item) pair0 Bid bid (Bid)
pair1
Retorna pares de referências
Apenas Items que têm Bid
E usando um left outer join com fetch
Query q session.createQuery("from Item item
left join fetch item.bids") Iterator items
q.list().iterator() while ( items.hasNext() )
Item item (Item) items.next() Bid bid
(Bid) item.getBid()
Retorna Items
Todos os Items inclusive os que não têm Bid
47
Cláusula select
  • Pode-se restringir os objetos retornados com uma
    cláusula select
  • Select é opcional em HQL (mas não em SQL)
  • A ausência do select equivale ao SQL select
  • Para que o inner join do exemplo anterior devolva
    apenas os itens (e não uma lista de Object com
    par item-bid) pode-se usar select
  • select item
  • from Item item
  • join item.bids bid
  • Exemplo

Query q session.createQuery("select i from Item
i join i.bids b") Iterator items
q.list().iterator() while ( items.hasNext() )
Item item (Item) items.next()
Agora temos uma lista de Items contendo apenas os
Items que têm Bids (inner join)
48
Joins implícitos
  • Ocorrem em associações -para-um (caminho
    convergente) e nunca em caminhos -para-muitos
  • O HQL a seguir causa três joins em SQL
  • from Bid bid where bid.item.category.name
    like 'Laptop' and bid.item.successfulBid.amo
    unt gt 100
  • E pode ser expresso explicitamente, usando
  • from Bid bid join bid.item item where
    item.category.name like 'Laptop and
    item.successfulBid.amount gt 100
  • Ou ainda
  • from Bid as bid join bid.item as item join
    item.category as cat join item.successfulBid
    as winningBid where cat.name like 'Laptop
    and winningBid.amount gt 100

Joins implícitossendo revelados
49
Produtos cartesianos (theta style joins)
  • Permite recuperar todas as combinações possíveis
    de instâncias de duas ou mais classes
  • Útil em classes não associadas
  • Condição de join deve estar na cláusula where
  • Apenas inner-join pode ser usado neste caso
  • Exemplo
  • Pode-se usar uma cláusula select para filtrar os
    resultados

Produto cartesiano
Query query session.createQuery("from User
user, LogRecord log " "where
user.username log.username") Iterator i
query.list().iterator() while ( i.hasNext() )
Object pair (Object) i.next() User
user (User) pair0 LogRecord log
(LogRecord) pair1
Condição de join
50
Comparação de identificadores
  • Queries que comparam chaves-primárias são
    realizados implicitamente em HQL
  • É o mesmo que comparar instâncias
  • Os dois queries ....
  • from Item i, User u where i.seller u and
    u.username 'steve'
  • from Item i, Bid b where i.seller b.bidder
  • São respectivamente equivalentes aos queries
  • from Item i, User u where i.seller.id u.id
    and u.username 'steve'
  • from Item i, Bid b where i.seller.id
    b.bidder.id

Esta última sintaxe permite que se passe
parâmetros (tipo, o id) para comparação.
51
Queries de relatórios
  • Relatórios geralmente focam nos dados
  • Instâncias não são importantes, mas valores
    selecionados, agrupados e organizados de certas
    instâncias
  • Dependem de recursos de seleção e agrupamento
  • Usa-se cláusulas select e group by / having.

52
Projeção cláusula select
  • Quais os dados desejados no resultado?
  • O query abaixo seleciona três propriedades de
    dois objetos
  • Os dados serão retornados em um vetor de Object
    de tamanho 3.
  • Os resultados não são entidades (são valores) e
    não são transacionais (serão usados para leitura,
    apenas)

Query query session.createQuery("select
item.id, item.description, bid.amount "
"from Item item join item.bids bid where
bid.amount gt 100") Iterator i
query.list().iterator() while ( i.hasNext() )
Object row (Object) i.next() Long id
(Long) row0 String description (String)
row1 BigDecimal amount (BigDecimal)
row2 ItemRow itemRow new ItemRow(id,
description, amount)
53
Instanciamento dinâmico
  • Hibernate permite o instanciamento dinâmico de
    objetos que são povoados pelos resultados do
    query
  • Evita o uso de vetores de objetos
  • É necessário que exista uma classe e construtor
    previamente construída

class ItemRow public ItemRow(Long id, String
description, BigDecimal amount) ... ...
Query query session.createQuery( "select
new ItemRow(item.id, item.description,
bid.amount)" "from Item item join item.bids
bid where bid.amount gt 100") Iterator i
query.list().iterator() while ( i.hasNext() )
ItemRow row (ItemRow) i.next() // ...
fazer alguma coisa
54
Distinct
  • Com o uso da cláusula select, os resultados de um
    query não mais tem garantia de serem distintos
  • A seguinte query pode retornar Items repetidos
  • select item.description from Item item
  • Para evitar duplicação, use a cláusula distinct
  • select distinct item.description from Item
    item

55
Funções agregadas
  • HQL suporta as seguintes funções na cláusula
    select
  • count() retorna Integer
  • min(), max(), sum() e avg() retornam BigDecimal

Integer count (Integer) session.createQuery(
"select count() from Item").uniqueResult() BigD
ecimal sum (BigDecimal) session.createQuery(
"select sum(item.successfulBid.amount) "
"from Item item").uniqueResult() Bi
gDecimal minmax (BigDecimal)
session.createQuery("select min(bid.amount),
max(bid.amount) "from Bid bid where
bid.item.id 1")
.uniqueResult() BigDecimal min
minmax0 BigDecimal max minmax1
56
Agrupamento
  • Se houver funções agregadas no select, não pode
    haver seleção de outros elementos, a menos que
    haja uma cláusula group by
  • Neste caso, os elementos deverão estar também no
    group by

select bid.item.id, count(bid), avg(bid.amount)
from Bid bid where bid.item.successfulBid is
null group by bid.item.id select bidItem.id,
count(bid), avg(bid.amount) from Bid bid
join bid.item bidItem where
bidItem.successfulBid is null group by
bidItem.id select item.id, count(bid),
avg(bid.amount) from Item item fetch join
item.bids bid where item.successfulBid is
null group by item.id
Um inner join implícito
Um inner join explícito
Um fetch (outer) join o agrupamento teve que ser
feito usando item.id
57
Restrição de grupos com having
  • Pode-se aplicar restrições no agrupamento com a
    cláusula having
  • select user.lastname, count(user) from User
    user group by user.lastname having
    user.lastname like 'A
  • Grupos requerem o uso de pelo menos dois aliases
    no select (a função e a propriedade de
    agrupamento)
  • Sempre que a cláusula select tem múltiplos
    aliases, o Hibernate devolve o resultado como
    (tuplas)vetores de Object
  • Chato de manipular inseguro quanto ao tipo
  • Ideal é usar select new e instanciar objetos
    dinamicamente
  • Agrupamento com instanciamento dinâmico
  • select new UsuarioReport(user.lastname,
    count(user)) from User user group by
    user.lastname having user.lastname like 'A

58
  • ...agora acabo! ?

59
Referências
  • Hibernate Reference Documentation
  • Hibernate in Action
Write a Comment
User Comments (0)
About PowerShow.com