java - with - spring jpa select




JPA e Hibernate-Critérios vs. JPQL ou HQL (14)

Quais são os prós e contras do uso de Criteria ou HQL ? A Criteria API é uma ótima maneira orientada a objetos para expressar consultas no Hibernate, mas, às vezes, Criteria Queries são mais difíceis de entender / construir do que o HQL.

Quando você usa critérios e quando HQL? O que você prefere em quais casos de uso? Ou é apenas uma questão de gosto?


A API de critérios é mais adequada para consultas geradas dinamicamente quando os filtros de consulta são aplicados dinamicamente em tempo de execução. Portanto, para evitar ataques de SQL Injection ao criar consultas dinâmicas, a Criteria API é uma ótima opção.

As consultas de critérios são menos expressivas e você pode acabar facilmente com uma consulta gerada por SQL muito complicada e ineficiente. Certa vez, entrei em um grande aplicativo corporativo em que a Criteria API era o método de consulta padrão e nem mesmo a revisão extensiva de código poderia superar o horror de não saber com quais consultas SQL iríamos acabar.

O JPQL ou HQL é muito mais expressivo e é muito mais fácil prever a consulta SQL gerada associada. Também é muito mais fácil revisar as consultas HQL de alguém do que as de Criteria.

A maioria dos casos de uso de consulta de entidade não exige cláusulas where dinâmicas, portanto, você pode implementar a maioria das consultas com o JPQL, deixando os Critérios para os dinâmicos.

Vale a pena notar que selecionar entidades com JPQL ou Criteria API faz sentido se você precisar modificá-las. Caso contrário, uma projeção de DTO terá um desempenho melhor. Confira este artigo para mais informações .


A maioria das respostas aqui é enganosa e menciona que Criteria Queries são mais lentos que o HQL , o que na verdade não é o caso.

Se você aprofundar e executar alguns testes, verá Critérios Consultas com desempenho muito melhor que o HQL normal .

E também com o Criteria Query você obtém o controle Orientado a Objetos que não está lá com o HQL .

Para mais informações, leia esta resposta here .


Critérios Api é um dos bons conceitos do Hibernate. de acordo com a minha opinião, estes são os poucos pontos pelos quais podemos fazer a diferença entre HQL e Criteria Api

  1. O HQL deve executar operações de seleção e não seleção nos dados, mas o Critério é apenas para selecionar os dados, não podemos executar operações não selecionadas usando critérios.
  2. O HQL é adequado para a execução de consultas estáticas, em que o critério é adequado para a execução de consultas dinâmicas.
  3. O HQL não suporta o conceito de paginação , mas podemos conseguir paginação com Critérios.
  4. Critérios usados ​​para levar mais tempo para executar do que o HQL.
  5. Com o Criteria, estamos seguros com o SQL Injection devido à sua geração de consultas dinâmicas, mas no HQL como suas consultas são fixas ou parametrizadas, não há segurança do SQL Injection

Critérios api fornecem um recurso distinto que nem o SQL nem o HQL fornecem. ie. permite a verificação do tempo de compilação de uma consulta.


Criteria é uma API orientada a objetos, enquanto HQL significa concatenação de strings. Isso significa que todos os benefícios da orientação a objetos se aplicam:

  1. Tudo o mais sendo igual, a versão OO é um pouco menos propensa a erros. Qualquer string antiga pode ser anexada à consulta HQL, enquanto apenas objetos Criteria válidos podem torná-la uma árvore de critérios. Efetivamente, as classes Criteria são mais restritas.
  2. Com o preenchimento automático, o OO é mais detectável (e, portanto, mais fácil de usar, pelo menos para mim). Você não precisa necessariamente lembrar quais partes da consulta vão para onde; o IDE pode ajudá-lo
  3. Você também não precisa se lembrar dos detalhes da sintaxe (como quais símbolos vão para onde). Tudo o que você precisa saber é como chamar métodos e criar objetos.

Como o HQL é muito parecido com o SQL (que a maioria dos desenvolvedores já conhece muito bem), esses argumentos "não precisa se lembrar" não carregam tanto peso. Se o HQL fosse mais diferente, isso seria mais importante.


Este post é bem antigo. A maioria das respostas fala sobre os critérios do Hibernate, não os critérios do JPA. JPA 2.1 adicionou CriteriaDelete / CriteriaUpdate e EntityGraph que controla o que exatamente buscar. A API de critérios é melhor, pois Java é OO. É por isso que o JPA é criado. Quando o JPQL é compilado, ele será traduzido para a árvore AST (modelo OO) antes de ser convertido para SQL.


Eu não quero chutar um cavalo morto aqui, mas é importante mencionar que as consultas Criteria agora estão obsoletas. Use o HQL.


Eu prefiro principalmente Criteria Queries para consultas dinâmicas. Por exemplo, é muito mais fácil adicionar alguma ordem dinamicamente ou deixar algumas partes (por exemplo, restrições), dependendo de algum parâmetro.

Por outro lado, estou usando o HQL para consultas estáticas e complexas, porque é muito mais fácil de entender / ler o HQL. Além disso, o HQL é um pouco mais poderoso, penso eu, por exemplo, para diferentes tipos de junção.


Existe outro caminho. Eu acabei criando um analisador HQL baseado na sintaxe original do hibernate para que ele primeiro analisasse o HQL, então ele poderia injetar dinamicamente parâmetros dinâmicos ou adicionar automaticamente alguns filtros comuns para as consultas HQL. Isso funciona muito bem!


Há uma diferença em termos de desempenho entre HQL e criteriaQuery, toda vez que você dispara uma consulta usando criteriaQuery, ele cria um novo alias para o nome da tabela que não reflete no último cache consultado de nenhum banco de dados. Isso leva a uma sobrecarga de compilação do SQL gerado, levando mais tempo para ser executado.

Em relação às estratégias de busca [http://www.hibernate.org/315.html]

  • O critério respeita as configurações de preguiça em seus mapeamentos e garante que o que você deseja carregar seja carregado. Isso significa que uma consulta Criteria pode resultar em várias instruções SELECT imediatas do SQL para buscar o subgráfico com todas as associações e coletas não-lazy mapeadas. Se você quiser alterar o "como" e até mesmo "o que", use setFetchMode () para habilitar ou desabilitar a busca de união externa para uma coleção ou associação específica. As consultas de critérios também respeitam completamente a estratégia de busca (join vs select vs subselect).
  • O HQL respeita as configurações de preguiça em seus mapeamentos e garante que o que você deseja carregar seja carregado. Isso significa que uma consulta HQL pode resultar em várias instruções SELECT imediatas do SQL para buscar o subgráfico com todas as associações e coletas não-lazy mapeadas. Se você quiser alterar o "como" e até mesmo o "o quê", use LEFT JOIN FETCH para ativar a busca de união externa para uma coleção particular ou associação anulável muitos para um ou um para um, ou JOIN FETCH para ativar junção interna buscando por uma associação muitos-para-um ou um-para-um não anulável. As consultas de HQL não respeitam nenhuma busca = "união" definida no documento de mapeamento.

O HQL pode causar problemas de segurança , como injeção de SQL.


Para mim, a maior vitória no Criteria é a API Example, onde você pode passar um objeto e o hibernate construirá uma consulta baseada nessas propriedades de objeto.

Além disso, a API de critérios tem suas peculiaridades (acredito que a equipe de hibernação está retrabalhando a API), como:

  • um criteria.createAlias ​​("obj") força uma junção interna em vez de uma possível junção externa
  • você não pode criar o mesmo alias duas vezes
  • Algumas cláusulas sql não possuem uma contrapartida de critérios simples (como uma subseleção)
  • etc.

Eu costumo usar HQL quando quero consultas semelhantes ao sql (excluir de usuários onde status = 'bloqueado') e tendem a usar critérios quando não quero usar o acréscimo de seqüência de caracteres.

Outra vantagem do HQL é que você pode definir todas as suas consultas antes e até mesmo externalizá-las em um arquivo ou algo assim.


Para usar o melhor dos dois mundos, a expressividade e a concisão do HQL e a natureza dinâmica dos Critérios consideram o uso do Querydsl .

Querydsl suporta JPA / Hibernate, JDO, SQL e Coleções.

Eu sou o mantenedor do Querydsl, então esta resposta é tendenciosa.


Usamos principalmente Critérios em nosso aplicativo no início, mas depois ele foi substituído pelo HQL devido a problemas de desempenho.
Principalmente, estamos usando consultas muito complexas com várias junções, o que leva a várias consultas nos Critérios, mas é muito otimizado em HQL.
O caso é que usamos apenas várias propriedades em objetos específicos e não em objetos completos. Com o critério, o problema também era concatenação de string.
Vamos dizer se você precisa exibir o nome e sobrenome do usuário em HQL é bastante fácil (name || ' ' || surname) mas em Crteria isso não é possível.
Para superar isso, usamos ResultTransormers, onde havia métodos onde tal concatenação era implementada para o resultado necessário.
Hoje usamos principalmente o HQL assim:

String hql = "select " +
            "c.uuid as uuid," +
            "c.name as name," +
            "c.objective as objective," +
            "c.startDate as startDate," +
            "c.endDate as endDate," +
            "c.description as description," +
            "s.status as status," +
            "t.type as type " +
            "from " + Campaign.class.getName() + " c " +
            "left join c.type t " +
            "left join c.status s";

Query query =  hibernateTemplate.getSessionFactory().getCurrentSession().getSession(EntityMode.MAP).createQuery(hql);
query.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
return query.list();

Portanto, no nosso caso, os registros retornados são mapas das propriedades necessárias.





hibernate-criteria