Hibernate

49
Hibernate Criteria x HQL/JPQL Fabrício Pereira Projeto Capacitar – GPE Maio/2013

description

11a edição do Projeto Capacitar na GPE Apresentação: Fabrício Pereira Maio de 2013.

Transcript of Hibernate

Page 1: Hibernate

HibernateCriteria x HQL/JPQLFabrício PereiraProjeto Capacitar – GPEMaio/2013

Page 2: Hibernate

Hibernate• Ferramenta ORM (Object-Relational Mapping)• Implementa a especificação JPA (Java Persistence API), e ainda

vai além fornecendo recursos adicionais• Não trata apenas do mapeamento de classes Java para tabelas

do banco de dados (e de tipos de dados Java para tipos de dados SQL), mas também oferece facilidades de consultas e recuperação de dados

2

Page 3: Hibernate

Hibernate• Consultas polimórficas• Linguagem de consulta orientada a objeto• HQL (Hibernate Query Language)• JPQL (Java Persistence Query Language)• Criteria API• Responsabiliza-se por transformar essas consultas em SQL

nativo e recuperar o resultado de acordo com mapeamento

3

Page 4: Hibernate

HQL / JPQL• Versão orientada a objeto do SQL• As consultas são definidas por uma string• JPQL é compatível com JPA• HQL atende a JPA, e possui mais recursos• Nem toda consulta HQL é JPQL• Toda consulta JPQL é HQL

4

Page 5: Hibernate

Criteria API• Especificada pela JPA, e novamente o Hibernate a implementa

com mais recursos• As consultas são definidas através da instanciação de objetos

Java que representam elementos da consulta• São usadas principalmente para consultas construídas

dinamicamente, e sua estrutura completa e exata só é conhecida em tempo de execução

5

Page 6: Hibernate

HQL / JPQL - Cláusulas• São quase as mesmas do SQL• select• from• where• order by• having• group by• insert• update• delete

6

Page 7: Hibernate

HQL / JPQL – Agregações• avg(...)• sum(...)• min(...)• max(...)• count(*)• count(...)• count(distinct ...)• count(all...)

7

Page 8: Hibernate

HQL / JPQL – Associações e Junções

• Explícito• inner join (join)• left outer join (left join)• right outer join (right join)• full join

• Implícito• Através da navegação (.) entre os objetos

• FETCH (força o retorno de uma propriedade lazy)• left join fetch• fetch all properties

8

Page 9: Hibernate

HQL / JPQL – Expressões• Operadores Matemáticos• +, -, *, /

• Operações Lógicas• and, or, not

• Operadores de comparação binária• =, >, <, >=, <=, <>, !=, like

• Outros operadores• in, not in, between, is null, is not null, is empty, is not empty, member of, not member of

• Parênteses indicando agrupamento• ( )

• Case• case [...] when ... then ... else ... end

9

Page 10: Hibernate

HQL / JPQL – Expressões• Concatenação de string• ||, concat(... , ...)

• Expressões EJB-QL 3.0• substring(), trim(), lower(), upper(), length(), locate(), abs(), sqrt(), bit_length(), mod()

• Expressões temporais• current_date(), current_time(), current_timestamp(), second(), minute(), hour(), day(), month(), year()

10

Page 11: Hibernate

HQL / JPQL – Expressões• Conversão de tipo• str(...), cast(... as ...), extract(... from ...)

• Operações em coleções• index(), size(), minelement(), maxelement(), minindex(), maxindex(), elements(), indices()

• some, all, exists, any, in

• Parâmetros posicionados e nomeados• ?• :nomeParametro

11

Page 12: Hibernate

HQL / JPQL – Sub-consultas• Dependente se o banco de dados suporta sub-consultas

12

Page 13: Hibernate

HQL / JPQL – Exemplos

• String hql = “from br.ufrj.Curso”;• org.hibernate.Query q = session.createQuery(hql);• List result = q.list();

• “from Curso”; // auto-import default• “from Curso as c”• “from Curso c”• “select c from Curso c”

13

Page 14: Hibernate

HQL / JPQL – Exemplos

• Consulta polimórfica• Experimentem !!• “from java.lang.Object o”

• Unique resultString hql = “from br.ufrj.Curso”;org.hibernate.Query q = session.createQuery(hql);

q.setMaxResult(1);Curso curso = q.uniqueResult();

14

Page 15: Hibernate

HQL / JPQL – ExemplosSELECT cust.name, cust.address, cust.phone, cust.id, cust.current_order

FROM customers AS custJOIN cust.store_customers AS scJOIN sc.stores AS store JOIN store.locations AS locJOIN loc.product AS prod

WHERE prod.name = 'widget‘AND loc.name IN ( 'Melbourne', 'Sydney' )AND prod.id = ALL (

SELECT item.prod_idFROM line_items item, orders oWHERE item.order_id = o.id

AND cust.current_order = o.id)

15

Page 16: Hibernate

HQL / JPQL – ExemplosSELECT order.id, SUM(price.amount), COUNT(item)FROM Order AS orderJOIN order.lineItems AS itemJOIN item.product AS product,Catalog AS catalogJOIN catalog.prices AS price

WHERE order.paid = falseAND order.customer = :customerAND price.product = productAND catalog = :currentCatalog

GROUP BY orderHAVING SUM(price.amount) > :minAmountORDER BY SUM(price.amount) DESC 16

Page 17: Hibernate

HQL / JPQL – Exemplos

• Restrição multi-colunas através de sub-consulta

from Usuario as usr where not (usr.nome, usr.idade) in (select aluno.nome, aluno.idade from Aluno aluno)

17

Page 18: Hibernate

HQL / JPQL – Interface Query• org.hibernate.Query• Esta interface oferece métodos para a• ligação de parâmetros• tratamento do conjunto de resultados (result set)• execução da consulta

18

Page 19: Hibernate

HQL / JPQL – Interface Query• Regras de retorno no result set• SEM a cláusula ‘select’

• Se a cláusula ‘from’ referencia uma única classe, cada linha do result set é uma instância dessa classe

• Se a cláusula ‘from’ referencia mais de uma classe, o result set é composto por ‘Object[]’ onde cada entrada é uma instância de cada classe referenciada

19

Page 20: Hibernate

HQL / JPQL – Interface Query• Regras de retorno no result set• COM a cláusula ‘select’

• Com um único elemento, cada linha do result set é uma instância desse elemento

• Com vários elementos, cada linha do result set é um ‘Object[]’ onde cada entrada é uma instância de cada elemento

20

Page 21: Hibernate

HQL / JPQL – Interface Query• Parâmetros

Query q = session.createQuery("from Foo as foo where foo.name=? and foo.size=?");

q.setString(0, “test”);q.setInt(1, 5);List foos = q.list();

21

Page 22: Hibernate

HQL / JPQL – Interface Query• Parâmetros Nomeados

Query q = session.createQuery("from Foo as foo where foo.name=:name and foo.size=:size");

q.setString(“name”, “test”);q.setInt(“size”, 5);List foos = q.list();

22

Page 23: Hibernate

HQL / JPQL – Interface Query• Propriedades de uma entidade pode ser ligada a parâmetros

nomeados da consulta

Foo fooBean = new Foo();fooBean.setName(“test”);fooBean.setSize(5);Query q = session.createQuery("from Foo as foo where foo.name=:name and foo.size=:size");

q.setProperties(fooBean);List foos = q.list(); 23

Page 24: Hibernate

HQL / JPQL – Interface Query• Paginação de Consultas

Query q = sess.createQuery("from DomesticCat cat");

q.setFirstResult(20);q.setMaxResults(10);List cats = q.list();

• Scroll

Query q = sess.createQuery("select cat.name, cat from DomesticCat cat " + "order by cat.name");

ScrollableResults cats = q.scroll();

24

Page 25: Hibernate

HQL / JPQL – Interface Query

• Named Queries@Entity@NamedQuery(name=“event.moreRecentThan",

query="select e from Event e where e.date >= :date")public class Event {...

}

public class TestDao {test() {

Query q = s.getNamedQuery(“event.moreRecentThan");q.setDate("date", aMonthAgo);List results = q.list();...

}...

}

25

Page 26: Hibernate

Criteria API – Interface Criteria• org.hibernate.Criteria• Essa interface representa uma consulta direcionada a uma

determinada classe persistente

26

Page 27: Hibernate

Criteria API - RestriçõesCriteria cr = session.createCriteria(ClassName.class);

cr.add(Restrictions.or(criterion1, criterion2));

dis = Restrictions.disjunction();dis.add(criterion1);dis.add(criterion2);cr.add(dis);

con = Restrictions.conjunction();con.add(criterion1);con.add(criterion2);cr.add(dis);

27

Page 28: Hibernate

Criteria API - Restrições• cr.add(Restrictions.eq());• cr.add(Restrictions.gt());• cr.add(Restrictions.ge());• cr.add(Restrictions.lt());• cr.add(Restrictions.le());• cr.add(Restrictions.like());• cr.add(Restrictions.ilike());• cr.add(Restrictions.between());• cr.add(Restrictions.isNull());• cr.add(Restrictions.isNotNull());• cr.add(Restrictions.isEmpty());• cr.add(Restrictions.isNotEmpty());

28

Page 29: Hibernate

Criteria API – Projeções e Agregações

• cr.setProjection(Projections.rowCount());• cr.setProjection(Projections.avg());• cr.setProjection(Projections.countDistinct());• cr.setProjection(Projections.max());• cr.setProjection(Projections.min());• cr.setProjection(Projections.sum());

29

Page 30: Hibernate

Criteria API – Ordenação e Paginação

• Ordenação• cr.addOrder(Order.asc());• cr.addOrder(Order.desc());

• Paginação• cr.setFirstResult(1);• cr.setMaxResult(10);• List result = cr.list();

• Scroll• ScrollableResults sc = cr.scroll();

30

Page 31: Hibernate

Criteria API – Associações e Junções

• Associação• Criteria cr1 = session.createCriteria(Usuario.class);• Criteria cr2 = cr1.createCriteria(“empresa”);

• Associação com Apelido• Criteria cr = session.createCriteria(Usuario.class);• cr.createAlias(“empresa”, “emp”) 31

Page 32: Hibernate

Criteria API – Associações e Junções

• Tipos de Junçõescriteria.createAlias("empresa", "emp", JoinType.INNER_JOIN);

criteria.createAlias("empresa", "emp", JoinType.LEFT_OUTER_JOIN);

criteria.createAlias("empresa", "emp", JoinType.RIGHT_OUTER_JOIN);

criteria.createAlias("empresa", "emp", JoinType.FULL_JOIN);

32

Page 33: Hibernate

Criteria API – Associações e Junções

• Dependendo das junções que se faça em uma mesma consulta, é necessário incluir o código abaixo, para que não retorne resultados inesperados

• criteria.setResultTransformer( CriteriaSpecification. DISTINCT_ROOT_ENTITY);

33

Page 34: Hibernate

Criteria API – Detached• Criteria Desacoplada da Sessãoorg.hibernate.criterion.DetachedCriteria

DetachedCriteria query = DetachedCriteria.forClass(Usuario.class)

.add( Property.forName(“perfil").eq(1) ); Session session = ....;List results =

query.getExecutableCriteria(session).list();session.close(); 34

Page 35: Hibernate

Criteria API – Detached• Sub-consultas com DetachedCriteriaDetachedCriteria mediaNota =

DetachedCriteria.forClass(Aluno.class). setProjection(Property.forName(“nota").avg());

session.createCriteria(Cat.class).add( Property.forName(“nota").gt(mediaNota)).list();

DetachedCriteria notas =

DetachedCriteria.forClass(Aluno.class). setProjection(Property.forName(“nota“));

session.createCriteria(Aluno.class).add( Subqueries.geAll(“nota", notas)).list(); 35

Page 36: Hibernate

Criteria API – Detached• Sub-consultas correlatas com DetachedCriteriaDetachedCriteria mediaNotaPorSexo = DetachedCriteria.forClass(Aluno.class, “aluno2“) .setProjection(Property.forName(“nota").avg()) .add(Property.forName(“aluno2.sexo").eqProperty(“aluno.sexo“));

session.createCriteria(Aluno.class, “aluno“) .add(Property.forName(“nota"). gt(mediaNotaPorSexo)).list();

36

Page 37: Hibernate

Criteria API – Detached• Restrição multi-colunas através de sub-consultaDetachedCriteria subConsulta = DetachedCriteria.forClass( Homem.class ) .setProjection( Projections.projectionList() .add(Projections.property( “peso" )) .add(Projections.property(“altura”))) .add(Restrictions.eq(“nome", “João”));

session.createCriteria( Mulher.class ).add( Subqueries.propertiesEq( new String[] { “peso", “altura" }, subConsulta )).list();

37

Page 38: Hibernate

Criteria API – Detached• Restrição multi-colunas através de sub-consultaDetachedCriteria subConsulta = DetachedCriteria.forClass( Homem.class ) .setProjection( Projections.projectionList() .add(Projections.property( “peso" )) .add(Projections.property(“altura”))) .add(Restrictions.eq(“nome", “João”));

session.createCriteria( Mulher.class ).add( Subqueries.propertiesEq( new String[] { “peso", “altura" }, subConsulta )).list();

38

Page 39: Hibernate

HQL/JPQL x Criteria API - Performance

• Alguns testes comprovam que a performance para as duas linguagens é muito próxima (um pequeno ganho com HQL), mas geralmente são falhos pois não exploram todas as situações de sobrecarga

• Pode-se obter uma performance alta quando for bem utilizada cada uma das linguagens

• Mas no dia a dia dos projetos, ocorrem situações em que as duas linguagens apresentam uma grande diferença de performance para determinadas consultas em bases legadas• HQL: < 100ms• Criteria: > 15s

39

Page 40: Hibernate

HQL/JPQL x Criteria API - Performance

• Custo da geração de SQL (em teoria)• Named HQL/JPQL Query - Geração de SQL ocorre apenas uma vez• Criteria - Sem necessidade de interpretar antes da geração• (non-named) HQL/JPQL Query - Realizar a interpretação e depois gera

• Escolher uma forma de consulta se baseando apenas nesses custo pode resultar em escolhas erradas ou inapropriadas

• Esse custo geralmente é desprezível comparado com o desempenho de um consulta diretamente em um DB

40

Page 41: Hibernate

HQL/JPQL x Criteria API - Performance

• Pontos a considerar na escolha• Dependência com a API Hibernate (porção imcompatível com JPA)• Criteria é muito útil em consultas com parâmetros opcionais• HQL/JPQL é apropriado na maioria das consultas que são pequenas e

fáceis de entender• NamedQuery quando o custo de geração de SQL for considerável, ou ao

otimizar HQL

41

Page 42: Hibernate

HQL/JPQL x Criteria API - Performance

• Recomenda-se que adote a medição do desempenho através de testes de carga como uma etapa natural na vida da aplicação, e assim não disponibilizar em produção apenas com micro benchmarks.

42

Page 43: Hibernate

HQL/JPQL x Criteria API

HQL/JPQL

• Definido por string• Erros detectados em

tempo execução• Similar ao SQL• Consultas estáticas• select/insert/update/

delete• Não é tão seguro quanto

a SQL Injection• Menos custoso

Criteria API

• Definido por objetos Java• Erros detectados em

tempo compilação• Não se parece com SQL• Consultas dinâmicas• Apenas select• Seguro quanto a SQL

Injection• Mais custoso 43

Page 44: Hibernate

HQL/JPQL x Criteria APIprivate Criteria

buildCriteriaAllFields(CampoOriginalVO campoOriginal,

MatchMode matchMode) {Criteria criteria =

getSession().createCriteria(getBeanClass());

if ((campoOriginal.getIdCampoOriginal() != null) && (!campoOriginal.getIdCampoOriginal().equals(new Long(0)))) {

criteria.add(Restrictions.idEq(campoOriginal.getIdCampoOriginal()));

}

if (campoOriginal.getOrigem() != null) {criteria.add(Restrictions.eq("origem", campoOriginal.getOrigem()));

}

if ((campoOriginal.getNomeCampo() != null) && (!campoOriginal.getNomeCampo().trim().isEmpty())) {criteria.add(Restrictions.eq("nomeCampo", campoOriginal.getNomeCampo()));

}

MetodoVO metodo = campoOriginal.getMetodo();if (metodo != null) {boolean idMetodoIsNotNull = (metodo.getIdMetodo()

!= null)&& (!metodo.getIdMetodo().equals(new Long(0)));boolean codigoMetodoIsNotNull =

(metodo.getCodigo() != null)&& (!metodo.getCodigo().trim().isEmpty());

if (idMetodoIsNotNull || codigoMetodoIsNotNull) {criteria.createAlias("metodo", "metodo");if (idMetodoIsNotNull) {criteria.add(Restrictions.eq("metodo.id", metodo.getIdMetodo()));} else if (codigoMetodoIsNotNull) {criteria.add(Restrictions.eq("metodo.codigo", metodo.getCodigo()));}

}}

criteria.addOrder(Order.asc("id"));

return criteria;}

44

Page 45: Hibernate

HQL/JPQL x Criteria APIprivate Criteria

buildCriteriaAllFields(DPVATServiceVO vo, MatchMode matchMode) {

Criteria criteria = getSession().createCriteria(getBeanClass());

if ((vo.getChassi() != null) && (!vo.getChassi().trim().equals(""))) {

criteria.add(Restrictions.eq("cod_chas", vo.getChassi().trim().toUpperCase()));

}

if ((vo.getPlaca() != null) && (!vo.getPlaca().trim().equals(""))) {

criteria.add(Restrictions.eq("cod_placa", vo.getPlaca().trim().toUpperCase()));

}

if ((vo.getUf() != null) && (!vo.getUf().trim().equals(""))) {criteria.add(Restrictions.eq("cod_uf_dut", vo.getUf().trim().toUpperCase()));

}

if ((vo.getCpfCnpj() != null) && (!vo.getCpfCnpj().trim().equals(""))) {criteria.add(Restrictions.eq("cod_cgc_cpf", Long.parseLong(vo.getCpfCnpj().trim())));

}

criteria.addOrder(Order.desc("num_ano_exerc"));

criteria.addOrder(Order.desc("dt_proc"));criteria.addOrder(Order.desc("dt_emis_guia"));

return criteria;}

Criteria: > 15s 45

Page 46: Hibernate

HQL/JPQL x Criteria APIprivate Query buildHqlQueryAllFields(DPVATServiceVO

vo, MatchMode matchMode) {String hqlRestrictions = "";

if ((vo.getChassi() != null) && (!vo.getChassi().trim().equals(""))) {

if (!hqlRestrictions.trim().isEmpty()) {hqlRestrictions += " and ";}hqlRestrictions += " siscon.cod_chas = '" +

vo.getChassi().trim().toUpperCase() + "' ";}

if ((vo.getPlaca() != null) && (!vo.getPlaca().trim().equals(""))) {

if (!hqlRestrictions.trim().isEmpty()) {hqlRestrictions += " and ";}hqlRestrictions += " siscon.cod_placa = '" +

vo.getPlaca().trim().toUpperCase() + "' ";}

if ((vo.getUf() != null) && (!vo.getUf().trim().equals(""))) {

if (!hqlRestrictions.trim().isEmpty()) {hqlRestrictions += " and ";}hqlRestrictions += " siscon.cod_uf_dut = '" +

vo.getUf().trim().toUpperCase() + "' ";}

if ((vo.getCpfCnpj() != null) && (!vo.getCpfCnpj().trim().equals(""))) {

if (!hqlRestrictions.trim().isEmpty()) {hqlRestrictions += " and ";}hqlRestrictions += " siscon.cod_cgc_cpf = "

+ Long.parseLong(vo.getCpfCnpj().trim()) + " ";

}

Query query = null;if (!hqlRestrictions.trim().isEmpty()) {query = getSession().createQuery("select siscon from Siscon siscon where " +

hqlRestrictions+ " order by siscon.num_ano_exerc desc,

siscon.dt_proc desc, siscon.dt_emis_guia desc");

}return query;}

HQL: < 100ms

46

Page 47: Hibernate

HQL/JPQL x Criteria API• Se não consegue o máximo e o melhor com o SQL puro, dificilmente

irá conseguir fazer o mesmo com HQL ou Criteria!

47

Page 48: Hibernate

Hibernate FAQ

https://community.jboss.org/en/hibernate/faq

• Performance• Dicas e Truques• Problemas Recorrentes• Problemas Avançados

48

Page 49: Hibernate

Muito [email protected]

49

www.myscrumhalf.com

www.gpetec.com.br