Hibernate: Consultas
Consultas - Introdução
Envolve alguns passos:
Criar a consulta com as restrições necessárias; Adicionar parâmetros à consulta;
Executar a consulta e recuperar o resultado
A forma de execução da consulta e obtenção dos dados pode ser configurada.
Consultas - Introdução
As consultas usando Hibernate podem ser feitas
de três formas:
SQL Nativo (SQLQuery);
HQL (Hibernate Query Language) (Query);
Consultas - Introdução
Query query = session.createQuery("from User");
Criteria criteria = session.createCriteria(User.class);
Objetos Query e Criteria são obtidos através do
Session
org.hibernate.Query org.hibernate.Criteria
SQL Nativo
O Hibernate permite especificar SQL escrito
manualmente:
Utilização da Interface SQLQuery;
A partir do objeto Session:
SQL Nativo – Consultas Escalares
//... Consultas Escalares (*)
Session session = sf.openSession();
SQLQuery sqlQuery = session.createSQLQuery(
"SELECT * FROM ANOTACOES.DEPARTAMENTO"); List resultado = sqlQuery.list();
for (int i = 0; i < resultado.size(); i++){ //Retorna cada linha da tabela
Object[] linha = (Object[]) resultado.get(i); System.out.print("ID = " + linha[0] + “ --> ”); System.out.println("NOME = " + linha[1] + “\n"); }
SQL Nativo – Consultas Escalares
Hibernate: SELECT * FROM DEPARTAMENTO
ID = 210 --> NOME = DEPARTAMENTO DE ENG. COMPUTACAO ID = 270 --> NOME = DEPARTAMENTO DE HISTORIA
ID = 300 --> NOME = DEPARTAMENTO DE MATEMATICA ID = 310 --> NOME = DEPARTAMENTO DIREITO
SQL Nativo – Consultas Escalares
//... Consultas Escalares (ESPECIFICANDO COLUNAS) Session session = sf.openSession();
SQLQuery sqlQuery = session.createSQLQuery(
"SELECT ID_DEPARTAMENTO, NOME FROM DEPARTAMENTO"); List resultado = sqlQuery.list();
for (int i = 0; i < resultado.size(); i++){ //Retorna cada linha da tabela
Object[] linha = (Object[]) resultado.get(i); System.out.print("ID = " + linha[0] + “ --> ”); System.out.println("NOME = " + linha[1] + “\n"); }
SQL Nativo – Consultas Escalares
Hibernate: SELECT ID_DEPARTAMENTO, NOME FROM DEPARTAMENTO
ID = 210 --> NOME = DEPARTAMENTO DE ENG. COMPUTACAO ID = 270 --> NOME = DEPARTAMENTO DE HISTORIA
ID = 300 --> NOME = DEPARTAMENTO DE MATEMATICA ID = 310 --> NOME = DEPARTAMENTO DIREITO
SQL Nativo – Entity Queries
//... Entity Queries – Especificando o Tipo de Retorno Session session = sf.openSession();
SQLQuery sqlQuery = session.createSQLQuery(
"SELECT * FROM DEPARTAMENTO WHERE ID_DEPARTAMENTO = ?"); sqlQuery.setInteger(0, 210); //Especificando parâmetros...
sqlQuery.addEntity(Departamento.class); //Especifica tipo do retorno
Departamento departamento = (Departamento) sqlQuery.uniqueResult(); //Retorna um resultado
session.close(); //...
SQL Nativo – Entity Queries
//... Entity Queries
Session session = sf.openSession();
SQLQuery sqlQuery = session.createSQLQuery( "SELECT * FROM DEPARTAMENTO");
sqlQuery.addEntity(Departamento.class); //Retorna todos os itens em uma coleção
Collection<Departamento> resultado = sqlQuery.list(); session.close();
SQL Nativo – Join’s
//... Entity Queries com Join
Session session = sf.openSession();
SQLQuery sqlQuery = session.createSQLQuery(
"SELECT * FROM DEPARTAMENTO D, CENTRO C WHERE D.ID_CENTRO = C.ID_CENTRO");
sqlQuery.addEntity("departamento", Departamento.class); sqlQuery.addJoin("centro", "departamento.centro");
List resultado = sqlQuery.list(); //...
SQL Nativo – Join’s
//... Entity Queries com Join
ArrayList<Departamento> departamentos = new ArrayList<Departamento>(); for (int i = 0; i < resultado.size(); i++) {
Object[] lista = (Object[]) resultado.get(i);
Departamento departamento = (Departamento) lista[0]; departamento.setCentro((Centro) lista[1]);
departamentos.add(departamento); }
session.close(); //...
HQL - Hibernate Query Language
O Hibernate possui uma linguagem própria para
recuperação dos objetos armazenados no banco de dados, a HQL;
HQL não segue nenhuma especificação, mas acabou
tornando-se referência na definição do padrão EJB3-QL, uma linguagem de objetos baseada na especificação
Enterprise JavaBeans 3;
Projetada para ser parecida com a SQL, mas com
suporte ao conceito de objetos;
HQL – Características
HQL não é executada diretamente no banco de dados. Ela é
executada sobre o serviço do Hibernate (Embora à primeira vista isso pode transparecer como sendo um processo mais lento, uma vez que mais uma camada existe entre a aplicação e o BD, na verdade isso não ocorre).
Durante a execução, os comandos HQL são mapeados para a versão SQL nativa do banco de dados utilizado, ou seja, o dialeto do próprio banco de dados é utilizado, o que se traduz em
desempenho, pois estruturas otimizadas de acesso podem ser utilizadas.
Com a execução sobre o serviço do Hibernate, os comandos HQL
HQL – Características
Efetua consulta de objetos ou propriedades
Possui suporte à herança (consultas polimórficas)
Permite fácil navegação entre associações de objetos Além dos tipos de usuário, opera sobre tipos java
nativos ou wrappers
String, boolean, Date, etc. Coleções Java e de usuário
Possui funções como na SQL: Agregação SUM AVG MIN MAX COUNT Expressões
IN, NOT IN, BETWEEN, IS NULL, IS EMPTY, etc.
Estruturas CASE (case ... when ... then ... else ... end) Funções de tempo: current_date(), minute(), etc.
Suporta qualquer operação definida pelo EJB3-QL
substring(), trim(), lower(), upper(), etc.
Funções escalares
sign(), trunc(), rtrim(), sin(), etc.
Funções para coleções
size(), minelement(), maxelement(), minindex(), etc.
Qualquer variável estática pública do Java
Color.RED, com.minhaEmpresa.comum.Sexo.MASCULINO
Suporte a ORDER BY, GROUP BY e HAVING;
Suporte a Subqueries (quando o BD suportar);
Faz junções implícitas pelas associações (ao efetuar
uma junção entre objetos (join) não é necessário especificar quais colunas devem fazer parte dessa
junção. Isso é automaticamente inferido pelo serviço do Hibernate, a partir das estruturas de chaves dos objetos relacionados.
HQL é case-insensitive, exceto para os nomes
das classes Java e propriedades.
Exemplificando: "SeLeCt" é a mesma coisa de
"SELECT", mas, "modelo.PESSOA" não é a
mesma coisa de "modelo.Pessoa" e "p.nome" é
diferente de "p.NOME".
É importante atentar a este detalhe para evitar
erros.
Adicionando Parâmetros pelo Nome
String queryString = "from Item item where item.description like :search";
Query q = session.createQuery(queryString).setString("search", searchString);
String queryString = "from Item item"
+ " where item.description like :search"
+ " and item.date > :minDate";
Query q = session.createQuery(queryString).setString("search", searchString).setDate("minDate", mDate);
Nome do parâmetro é precedido de “:”
O valores são adicionados através de métodos
Executando a Consulta
Se mais de um objeto pode ser retornado,
chama-se o método list()
List list = query.list();
Se somente um objeto pode ser retornado,
chama-se o método uniqueResult()
User user = (User) query.uniqueResult();
O método retorna null se nenhum objeto for encontrado;
Executando a Consulta
Query query = session.createQuery("from User"); List<User> list = query.list();
for (User user : list) {
System.out.println(user.getName());
}
Query query2 = session.createQuery(
"from User user where user.name =:name").setString("name",
"SUNSP");
User user = (User) query2.uniqueResult();
Consultas Básicas
A consulta mais simples tem somente a cláusula
FROM
“from Item”
Para se referenciar as propriedades de uma
entidade, um ALIAS deve ser criado
“from Item as item”
“from Item item”
Palavra chave “as” é opcional
Operador LIKE pode ser utilizado
“%” representa qualquer seqüência de caracteres
_ (Under_Score) representa qualquer caractere
“from User u where u.firstname like 'G%'”
Negação pode ser utilizada
“from User u where u.firstname not like '%Foo B%'”
Operadores lógicos e parênteses
“from User user where user.firstname like 'G%' and user.lastname like 'K%'”
Comparações
Operadores lógicos e parênteses
“from User u where (u.firstname like 'G%' and u.lastname like 'K%' ) or u.email in
('[email protected]', '[email protected]' )”
Coleções
Comparações
Funções podem ser chamadas a partir do
HQL
HQL permite a chamada de funções SQL na cláusula WHERE
Funções UPPER() e LOWER()
"from User u where lower(u.email) = '[email protected]'"
Função SIZE()
from Item i where size(i.bids) > 3
Comparações
Outras funções
CONCAT(s1, s2)
SUBSTRING(s, offset, length)
Offset começa a partir de 1
TRIM( [[BOTH|LEADING|TRAILING] s)
"from Item i where TRIM(BOTH i.name) = 'Computador'"
LENGTH(s)
LOCATE(search, s, offset)
Ordenando o Resultado
A Cláusula ORDER BY é utilizada para ordenar
o resultado
"from User u order by u.name"
Ordem ascendente ou descendente
Utiliza-se asc ou descfrom User u order by u.username desc
Ordenando por mais de uma propriedade
“from User u order by u.lastname asc, u.firstname asc”
Junções
A habilidade de realizar junções é uma das
principais forças do modelo relacional
Permite selecionar diferentes objetos associados
Inner Join
Contém somente os registros que estão
relacionados com o outro lado da junção
(left) Outer Join
Retorna todos os Itens
Dados de Bid são preenchidos com NULL se não houver uma correspondência
Junção com HQL
Coluna de junção não precisar ser informada na
consulta
Informação é extraída do mapeamento
É necessário ser informado somente o nome da
associação
Nome do atributo que referencia a classe ou coleção de classes
Joins podem ser executados de duas maneiras
Join implícitos na Associação
Join Implícito na Associação
O Join é realizado através da associação entre duas
entidades
Exemplo:
“from Bid bid where bid.item.description like '%Foo%'” Bid é associado a Item através do atributo “item”
Hibernate sabe que a associação está mapeada a partir da chave estrangeira ITEM_ID da tabela BID
Joins implícitos são sempre realizados através de
Join Implícito na Associação
Múltiplos joins são possíveis
from Bid bid where bid.item.category.name like 'Laptop%'
Join especificado na Cláusula FROM
Joins podem ser especificados explicitamente na
cláusula FROM
Exemplo
"select i from Item i join i.bids b where b.amount > 10"
Aliases devem ser especificados na cláusula FROM e
utilizados na cláusula WHERE
Cláusula SELECT é utilizada para que somente Itens
Join especificado na Cláusula FROM
Na consulta, um Item pode ser retornado mais de uma
vez
Uma para cada Bid associado
Somente uma instância é utilizada
A consulta possui o mesmo formato para associações
Outer Joins
Para a utilização de Outer Joins utiliza-se a cláusula
LEFT JOIN
LEFT OUTER JOIN e RIGHT OUTER JOIN também podem ser utilizados
A cláusula WITH é utilizada para adicionar restrições "select i from Item i left join i.bids b with b.amount >= 9"
Comparando Identificadores
Na Orientação a Objetos não são os identificadores,
mas as referências ao objetos que são comparadas
Comparações podem ser feitas através dos atributos
das entidades
"select i from Item i join i.bids b where i.seller = b.bidder"
i.seller e b.bidder representam referências para a entidade User Retorna os Itens em que o próprio vendedor deu um lance
Comparando Identificadores
Entidades também podem ser adicionadas como
parâmetros de uma consulta
Query query = session.createQuery("from Item i where i.seller = :seller");
HQL – Exemplos
Q1: from Aluno //Busca todos
Q2: from Aluno as alu //Uso de alias
Q3: from Aluno aluno where aluno.matricula >= 35 Q4: from Endereco end
where
( end.rua in
("Bernardo Vieira", "Prudente de Morais") ) or ( end.numero between 1 and 100 )
Q5: from Professor p where p.nome like "João%“ Q6: from Aluno aluno order by aluno.nome asc
HQl – Exemplos (JOIN’s)
inner join;
left outer join;
right outer join;
full 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 from Cat as cat where cat.mate.name like '%s%'
HQL – Cláusula select
select mate from Cat as cat join cat.mate as mate select cat.mate from Cat cat
select cat.name from DomesticCat cat where cat.name like 'fri%' select cust.name.firstName from Customer as cust
//Retorno em um array de Object[] select mother, offspr, mate.name
from DomesticCat as mother
inner join mother.mate as mate
HQL – Cláusula where
from Cat where name='Fritz'
from Cat as cat where cat.name='Fritz'
select foo from Foo foo, Bar bar where foo.startDate = bar.date from Cat cat where cat.mate.name is not null
select cat, mate from Cat cat, Cat mate where cat.mate = mate from AuditLog log, Payment payment
HQL – Expressões
from DomesticCat cat where cat.name between 'A' and 'B' from DomesticCat cat
where cat.name in ( 'Foo', 'Bar', 'Baz' ) from Cat cat where cat.alive = true
Fontes Bibliográficas:
Java Persistence com Hibernate. Christian Bauer,
Gavin King. Editora Ciência Moderna, 2007.
Hibernate: Manual de Referência. Disponível em: