350 likes | 466 Views
Hibernate: Consultas. Francisco do Nascimento PSC - Programação de Softwares Corporativos UNIBRATEC, outubro de 2008. Consultas. Umas das partes mais interessantes do acesso a dados
E N D
Hibernate: Consultas Francisco do Nascimento PSC - Programação de Softwares Corporativos UNIBRATEC, outubro de 2008
Consultas • Umas das partes mais interessantes do acesso a dados • Consultas complexas podem levar um bom tempo para serem escritas e podem ter considerável impacto na performance da aplicação • Consultas são escritas utilizando conceitos de orientação a objetos • Objetos no lugar de tabelas • Propriedades no lugar de colunas • Experiência em SQL não é desprezada
Consultas • Podem ser feitas de três maneiras • Hibernate Query Language (HQL) • Criteria API e Query by Example • Utilizando SQL
Consultas: Exemplos // Através de HQL session.createQuery("from Category c where c.name like 'Laptop%'"); // Utilizando-se Criteria session.createCriteria(Category.class).add( Restrictions.like("name", "Laptop%")); // Através de SQL session.createSQLQuery( "select * from cad.CATEGORY where name_category like 'Laptop%'");
Consultas • 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
Criando a Consulta • Objetos Query e Criteria são obtidos através do Session • org.hibernate.Query • org.hibernate.Criteria Query query = session.createQuery("from User"); Criteria criteria = session.createCriteria(User.class);
Adicionando Parâmetros à Consulta • Parâmetros não devem ser adicionados na própria String da consulta • "from Item i where i.description like '" + search + "'" • Parâmetros podem ser adicionados através de sua posição ou de seu nome
Adicionando Parâmetros pelo Nome • Nome do parâmetro é precedido de “:” • O valores são adicionados através de métodos sets 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);
Adicionando Parâmetros pela Posição • A consulta contém “?” para indicar a existência de alguma parâmetro • Os valores também são adicionado através de métodos sets String queryString = "from Item item" + " where item.description like ?" + " and item.date > ?"; Query q = session.createQuery(queryString).setString(0, searchString).setDate(1, minDate);
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 • Se a consulta retornar mais de um objetos, a exceção NonUniqueResultException é lançada
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(); System.out.println(user.getName());
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 • A consulta não é case-sensitive • “FROM Item AS item” também pode ser utilizada
Consultas Polimórficas • Consultas podem ser escritas utilizando polimorfismo • “from Pessoa” • Retorna todas as entidades que herdam de Pessoa • Aluno • Professor
Restrições • Geralmente não se quer trazer todo o conteúdo da tabela • Restrições devem ser adicionadas para restringir os objetos retornados • HQL também utiliza-se a cláusula WHERE • As restrições são feitas sobre propriedades da entidade
Restrições • Literais e condições podem ser incluídos • Utiliza-se aspas simples para literais do tipo String • “from Usuario u where u.email = 'foo@hibernate.org'” • “from Item i where i.ativo = true” • Comparações podem ser realizadas • “from Produto p where p.quantidade between 1 and 10” • “from Produto p where p.quantidade > 100” • “from Usuario u where u.email in ('foo@bar', 'bar@foo')”
Comparações • Operador LIKE pode ser utilizado • “%” representa qualquer seqüência de caracteres • _ (Under_Score) representa qualquer caractere • “from Usuario u where u.nome like 'G%'” • Negação pode ser utilizada • “from Usuario u where u.nome not like '%Foo B%'” • Operadores lógicos e parênteses • “from Usuario user where user.nome like 'G%' and user.sobrenome like 'K%'”
Comparações • Operadores lógicos e parênteses • “from Usuario u where (u.nome like 'G%' and u.sobrenome like 'K%' ) or u.email in ('foo@hibernate.org', 'bar@hibernate.org' )” • Coleções • "from Venda d where d.itens is not empty"
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 podem ser definidas pelo usuário • Depende do suporte do banco de dados • Funções UPPER() e LOWER() • "from Usuario u where lower(u.email) = 'foo@hibernate.org'" • Função SIZE() • from Venda v where size(v.itens) > 3 • E muitas outras...
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) • Procura a localização de uma substring dentro de uma string
Comparações • Outras funções • CURRENT_DATE(), CURRENT_TIME(), CURRENT_TIMESTAMP() • Valores retornados são referentes ao SGBD • SECOND(d), MINUTE(d), HOUR(d), DAY(d), MONTH(d), YEAR(d) • Extraem os valores de um argumento temporal
Ordenando o Resultado • A Cláusula ORDER BY é utilizada para ordenar o resultado • "from Usuario u order by u.nome" • Ordem ascendente ou descendente • Utiliza-se asc ou desc • from Usuario u order by u.login desc • Ordenando por mais de uma propriedade • “from Usuario u order by u.sobrenome asc, u.nome asc”
Junções • A habilidade de realizar junções é uma das principais forças do modelo relacional • Permite selecionar diferentes objetos associados e coleções em uma única consulta
Inner Join • Contém somente os registros que estão relacionados com o outro lado da junção • Contém somente os Itens que possuem Bids
(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 especificado na cláusula FROM
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 associações many-to-one ou one-to-one
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 sejam retornados
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 many-to-one e one-to-one
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" • Itens que não possuem Bids também são retornados
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"); query.setEntity("seller", user);
HQL • Consultas não precisam aparecer no código • Na verdade, muitas vezes é melhor que não apareçam • Podem ficar nos metadados e serem chamadas pelo nome • Usa-se o método getNamedQuery() • Mas antes, ela precisa ser declarada em algum arquivo de mapeamento ou anotada em alguma entidade List clientes = session.getNamedQuery(“findClienteByName”) .setString(“nome”, nome),list() <query name=“findClienteByName”><![CDATA[ from Cliente c where c.nome like :nome]] </query>
NamedQueries com Annotation package auction.model; import ...; @NamedQueries({ @NamedQuery( name = "findItemsByDescription", query = "select i from Item i where i.description like :desc" ), ... }) @Entity @Table(name = "ITEM") public class Item { ... }
Paginando o resultado Query query = session.createQuery("from User u order by u.name asc"); query.setFirstResult(5); query.setMaxResults(10);
Instanciação dinâmica select new Aluno( a.id, a.nome, a.idade, a.curso ) from Aluno a where a.curso is not null group by a.nome