Title: Hibernate
1Hibernate conceitos e consultas
- Jobson Ronan jrjs_at_cin.ufpe.br
2Objetivos
- Aprender sobre os conceitos de persistência
relacionados ao Hibernate - Aprender como recuperar os dados e efetuar
consultas de maneira eficientemente no Hibernate
3Ciclo 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
4Diagrama de estados
5Objetos 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
6Objetos 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
7Objetos 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)
8Como 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()
9Como 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()
10Como 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()
11Como 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()
12Como 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()
13Como 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()
14API 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.
15Session 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
16Recuperaçã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
17Recuperaçã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
18HQL
- 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()
19HQL
- 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
20Consulta 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()
21Como 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
22Estraté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
23Lazy 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
24LazyInitializationException
- 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!
25Recuperaçã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
26Eager 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
27Qual 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.
28outer-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
29Em 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
30Consultas 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()
31Passagem 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)
32Passagem 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()
33Queries 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
34Aliases
- 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
35Queries 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()
36Mais 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
37Mais HQL Restrições (where)
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
38Mais 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'
39Mais 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 41Joins
- 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
42SQL 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
43Joins 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
44Fetch 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
45Join 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)
46inner 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
47Clá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)
48Joins 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
49Produtos 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
50Comparaçã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.
51Queries 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.
52Projeçã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)
53Instanciamento 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
54Distinct
- 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
55Funçõ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
56Agrupamento
- 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
57Restriçã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 59Referências
- Hibernate Reference Documentation
- Hibernate in Action