• Nenhum resultado encontrado

Hibernate – conceitos e consultas

N/A
N/A
Protected

Academic year: 2022

Share "Hibernate – conceitos e consultas"

Copied!
59
0
0

Texto

(1)

Hibernate – conceitos e consultas

Jobson Ronan

{[email protected]}

(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.openSession();

Transaction tx = sessionTwo.beginTransaction();

sessionTwo.update(user);

user.setUsername("jonny"); // 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();

Transaction 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();

Transaction 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();

Transaction tx = session.beginTransaction();

session.delete(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.class);

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().commit();

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-join=“auto” (default).

O comportamento é lazy, se o outro lado (singular) da associação especificar, ou eager, se não especificado.

outer-join=“true”

Comportamento é sempre eager para esta associação (logo diferentes associações para mesmo objeto podem ter estratégias diferentes)

outer-join=“false”

Se o objeto tiver sido mapeado como lazy, ocorre lazy fetching, caso contrário, immediate fetching (SQL select)

Exemplo:

<many-to-one name="item" class="Item" outer-join="true">

(29)

Em coleções

Lazy

Use atributo lazy=“true” (não depende de proxy do outro lado)

<set name="bids" lazy="true">

Batched Lazy

Acrescente o atributo batch-size=“tamanho”

(refere-se ao número de coleções

<set name="bids" lazy="true" batch-size="9">

Eager

Use atributo outer-join=“true”

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);

query.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 > ?";

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("findItemsByDescription") .setString("description", description).list();

<query name="findItemsByDescription"><![CDATA[

from Item item where item.description like :description ]]></query>

(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 livro

where 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.Object.class) .list();

BillingDetails

CreditCard BankAccount

(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 = '[email protected]

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: =, <>, <, >, >=, <=, 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 > 100

from User u where u.email in ( "[email protected]", "[email protected]" ) from User u where u.email is null

from Bid bid where ( bid.amount / 0.71 ) - 100.0 > 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) = '[email protected]'

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 ( "[email protected]", "[email protected]" )

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

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

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

(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 > 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

E usando um left outer join com fetch

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) pair[0];

Bid bid = (Bid) pair[1];

}

Retorna pares de referências

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 Apenas

Items que têm Bid

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.amount > 100

E pode ser expresso explicitamente, usando

from Bid bid

join bid.item item

where item.category.name like 'Laptop%‘

and item.successfulBid.amount > 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 > 100

Joins implícitos sendo 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

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) pair[0];

LogRecord log = (LogRecord) pair[1];

}

Produto cartesiano

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.idEsta ú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 > 100");

Iterator i = query.list().iterator();

while ( i.hasNext() ) {

Object[] row = (Object[]) i.next();

Long id = (Long) row[0];

String description = (String) row[1];

BigDecimal amount = (BigDecimal) row[2];

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

Query query =

session.createQuery(

"select new ItemRow(item.id, item.description, bid.amount)"

+ "from Item item join item.bids bid where bid.amount > 100");

Iterator i = query.list().iterator();

while ( i.hasNext() ) {

ItemRow row = (ItemRow) i.next();

// ... fazer alguma coisa }

class ItemRow {

public ItemRow(Long id, String description, BigDecimal amount) {...}

...

}

(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();

BigDecimal sum = (BigDecimal)

session.createQuery("select sum(item.successfulBid.amount) "

+"from Item item").uniqueResult();

BigDecimal[] minmax = (BigDecimal[])

session.createQuery("select min(bid.amount), max(bid.amount) “ +"from Bid bid where bid.item.id = 1")

.uniqueResult();

BigDecimal min = minmax[0];

BigDecimal max = minmax[1];

(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 fetch (outer) join; o

agrupamento

teve que ser feito usando item.id

Um inner join

explícito Um inner join

implícito

(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

Referências

Documentos relacionados

Procura-se também analisar o clima dos municípios brasileiros banhados pelo reservatório de Itaipu, bem como conhecer os principais processos impactantes, tanto

1 — Os apoios são concedidos pela Câmara Municipal da Guarda às IPSS legalmente cons- tituídas de acordo com o estipulado no n.º 3, do artigo 2.º do presente Regulamento... 2 —

Este producto se ha diseñado para inmovilizar la columna cervical en una posición neutra durante el transporte, en combinación con otros dispositivos de inmovilización cervical

c) select curso.nome as curso, alunos from discente inner join curso on discente.curso_id = curso.id group by curso.nome having count(discente.id) as alunos order by curso.nome.

Outras cláusulas que o comando select apresenta são DISTINCT, ORDER BY, GROUP BY, INNER JOIN, entre outras.. DISTINCT: Várias linhas de uma tabela podem conter os mesmos valores

Tabela 2- Características do registro de enfermagem quanto à tentativa de reanimação cardiopulmonar em pacientes que sofreram parada cardiorrespiratória em duas unidades de terapia

A Lista de Fauna Ameaçada de Extinção e os Entraves para a Inclusão de Espécies – o Exemplo dos Peixes Troglóbios Brasileiros.. The List of Endangered Fauna and Impediments

As sementes foram submetidas a tratamentos para superação da d o r m ê n c i a , sendo utilizados os tratamentos: testemunha (sementes não tratadas); escarificação mecânica em