JPA não tem uma API de Criteria? Que absurdo é esse?

39 respostas
Mauricio_Linhares

Assim, finalmente resolvi gastar alguns momentos do meu precioso tempo pra aprender JPA utilizando o Hibernate e eis que eu descubro uma coisa no mínimo bizarra.

A especificação não tem uma API equivalente a Criteria do Hibernate!

E o pior, os “líderes” da especificação acharam que a api de criteria é um requisito exótico e que não valia a pena ser adicionado na especificação.

Agora eu pergunto aos gênios que tiveram essa maravilhosa idéia, se eu tiver que montar uma query em tempo de execução (dinamicamente) eu vou ter que fazer concatenação de Strings em EJB-QL? Isso é absurdo!

Pronto, agora é que eu não migro do Hibernate mas nem amarrado, porque eu é que não vou ficar fazerndo concatenação de Strings e fazendo binding de parâmetros porque algum i$%@ta achou que uma coisa básica como uma API de busca absolutamente orientada a objetos é um “requisito exótico” em uma ferramenta de mapeamento objeto relacional.

Desculpem o abuso e as palavras baixas, mas isso realmente foi demais pra mim. Desse jeito, EJB vai continua sendo só hype mesmo, porque até na hora de copiar o que presta os caras se perdem, nã…

39 Respostas

F

Mauricio,

É uma pena mesmo, o EJB3 deu uma boa evoluida, mas quem utiliza-lo vai continuar preso a sua implementacao. Se eu usar EJB3 com Hibernate vou ficar preso ao recusos extras dele, Criteria, validacoes e por ai vai. O mesmo serve pro TopLink ou outros que surgirem.

Quem sabe na proxima eles acertam.

Eu so nao sei se isso foi de proprosito pois um dos responsaveis por isso é o proprio Gavin assim o Hibernate continua com um diferencia frente ao EJB3.

]['s

urubatan

não foi de proposito isto não …
o Hibernate continua na frente da JPA por que o Gavin King pegou as ideias reprovadas na spec e colocou no hibernate :smiley:

marcelomartins

Pois é, pra mim EJB continua sendo Stateless Session Bean, e só!

urubatan

yeap, mas agora muito mais fácil :smiley:

chun

Descordo… acho que Entitys do EJB 3 ficaram bem legais… calro que voce nao tem criteria (puts… quantos % da sua plicação voce monta query dinamica ? 1% ? 2% ? ) e ao contrario das declaracoes aqui… nao fica preso nao… a nao ser que voce USE caracteristicas proprias… se voce usar o padrao… fica tudo compativel (uso hibernate e toplink aqui mudando 1 linha do XML persistence.xml )

Acho que é exagero falar que “EJB” eh soh session… os Entitys 3 ficaram bem legais…

Eu prefiro sacrificar algumas “novidades” do que deixar meu software na mão de um fornecedor apenas…

A integracao transparente do EntityManager não tem preço.

pcalcado

Alémd e ter muito mais de 1% de consultas dinamicas o fato de ter consultas OO faz muita falta no modelo novo.

Eventualmente Criteria vai entrar no EJB3.1, até lá…

Mauricio_Linhares

chun:
Descordo… acho que Entitys do EJB 3 ficaram bem legais… calro que voce nao tem criteria (puts… quantos % da sua plicação voce monta query dinamica ? 1% ? 2% ? ) e ao contrario das declaracoes aqui… nao fica preso nao… a nao ser que voce USE caracteristicas proprias… se voce usar o padrao… fica tudo compativel (uso hibernate e toplink aqui mudando 1 linha do XML persistence.xml )

Rapaz, se você acha que fazer concatenação de Strings é uma coisa boa e normal, boa sorte. Eu, pessoalmente, detesto.

Thiago_Senna

Como de prática, se alguém não faz, outro faz.

A fonte é este artigo: Spring 2 Final Approching with new support for OSGi, JPA, Asynch JMS

Enquanto não sai o Ejb 3.1, a gente continua no spring… :stuck_out_tongue:

chun

Maurício Linhares:
chun:
Descordo… acho que Entitys do EJB 3 ficaram bem legais… calro que voce nao tem criteria (puts… quantos % da sua plicação voce monta query dinamica ? 1% ? 2% ? ) e ao contrario das declaracoes aqui… nao fica preso nao… a nao ser que voce USE caracteristicas proprias… se voce usar o padrao… fica tudo compativel (uso hibernate e toplink aqui mudando 1 linha do XML persistence.xml )

Rapaz, se você acha que fazer concatenação de Strings é uma coisa boa e normal, boa sorte. Eu, pessoalmente, detesto.

Eu detesto tmb… mas continuo afirmando que Querys dinamicas são praticamente 1 ou 2% da minha app , entao não costumo fazer tempestade em um copo d’agua… é s´po separar e pronto…

Odeio acessar via JNI as coisas… mais eh 1% de tudo tmb… entao… prefiro conviver com isso a ficar preso a um unico fornecedor.

Na minha opiniao , isso não é motivo suficiente para deixar JPA de lado… ela proporciona uma integracao muito boa… e a vida eh feita de escolhas :wink:

RafaelRio

A falta da API de criteria no JPA é realmente motivo suficiente pra chorar soluçando!

Mas é possível criar queries dinâmicas sem concatenar strings através de @NamedQueries e @NamedQuery. Ex: @Entity @Table(name = "produto") @NamedQueries( { @NamedQuery( name = "Produto.findByDescricao", query = "SELECT p FROM Produto p WHERE p.descricao = :descricao"), @NamedQuery( name = "Produto.findByPreco", query = "SELECT p FROM Produto p WHERE p.preco = ?1") } ) public class Produto implements Serializable { . . . // Implementação do Entity Bean. }

public class ProdutoDAO ...
     . . .

     public List<Produto> findByPreco(final BigDecimal preco) {
          return manager.createNamedQuery("Produto.findByPreco").
                         /* Positional Parameter in Query */
                         setParameter(1, preco).getResultList();
     }

     . . .
}

Também é possível criar a query através do método createQuery do EntityManager.

public class ProdutoDAO ...
     . . .

     public Produto findByName(final String nome) {
          Produto temp = null;
          try {
               temp = (Produto) manager.createQuery(
                              "SELECT p FROM Produto p WHERE p.nome LIKE :nome")
                               /* Named Parameter in Query */
                              .setParameter("nome", nome).getSingleResult();
          } catch(Exception e) {
               e.printStackTrace();
          }
          return temp;
     }
     . . .
}
marcus.floriano

Apenas para constar que existe solução.

Esse exemplo do Diogo Romeo mostra como fazer.

http://www.nabble.com/Re:-Dúvidas-sobre-JPA-p15185421.html

Mauricio_Linhares

marcus.floriano:
Esse exemplo do Diogo Romeo mostra como fazer.

http://www.nabble.com/Re:-Dúvidas-sobre-JPA-p15185421.html

E qual é a solução? Usar o Hibernate? :lol:

De qualquer forma, eu já tinha mostrado um DAO genérico como esse há bons dois anos atrás -> http://www.guj.com.br/posts/downloadAttach/327.java

marcus.floriano

Maurício Linhares:
marcus.floriano:
Esse exemplo do Diogo Romeo mostra como fazer.

http://www.nabble.com/Re:-Dúvidas-sobre-JPA-p15185421.html

E qual é a solução? Usar o Hibernate? :lol:

De qualquer forma, eu já tinha mostrado um DAO genérico como esse há bons dois anos atrás -> http://www.guj.com.br/posts/downloadAttach/327.java

Maurício, muito bom esse documento, sobre esse assunto do tópico informando que a JPA não tem o Criteria, a especificação JPA não tem o especifica o Criteria (pode me corrigir se estiver errado), mas para trabalhar com JPA temos que utilizar algum mecanismo que implementou a JPA sendo assim utilizamos o Hibernete ou Toplink, certo?

Qual é o problema utilizar o que tem de amais no Hibernet ou no Toplink, pois o tópico desse forum “JPA não tem uma API de Criteria? Que absurdo é esse?” não é verdade conforme o exemplo que mandei e segue o pequeno trecho abaixo:

public List<T> findByExample(T instance) throws DAOException { Session session = (Session) getEntityManager().getDelegate(); Example example = Example.create(instance).excludeZeroes(); Criteria criteria = session.createCriteria(instance.getClass()).add(example); return criteria.list(); }

Estou enganado?

Mauricio_Linhares

marcus.floriano:
Qual é o problema utilizar o que tem de amais no Hibernet ou no Toplink, pois o tópico desse forum “JPA não tem uma API de Criteria? Que absurdo é esse?” não é verdade conforme o exemplo que mandei e segue o pequeno trecho abaixo:

public List<T> findByExample(T instance) throws DAOException { Session session = (Session) getEntityManager().getDelegate(); Example example = Example.create(instance).excludeZeroes(); Criteria criteria = session.createCriteria(instance.getClass()).add(example); return criteria.list(); }

Estou enganado?

Está, esse código não funciona pro TopLink, só pro Hibernate.

sergiotaborda

Não , não… eles não querem que vc faça concatenação de strings. eles querem que vc use StringBuilder. lol

Leozin

puta que pariu, phoenix down no tópico

mas whatever, sobre a API de critéria, o que talvez possa ser interessante é, caso tu queira um negócio mais “compatível” com o resto das coisas, ou usa um QueryObject ou usa a API de critéria do Hibernate ou Toplink. Ambos tem suas respectivas implementações, basta dar uma olhada

abraços

Kenobi

Complicado mesmo Maurício. Nesse exato momento estou escrevendo um componente adicional para o WLI ( Weblogic Integration - Apache Beehive) encapsulando a persistência no modelo ORM.

Como vou utillizá-lo dentro de um processo ( JSR 207), todas as queries serão dinâmicas.

Infelizmente ele vai ter de mudar de nome para HibernateControl, rsss até a JPA 2 sair do papel … :roll:

Mauricio_Linhares

Pois é, só percebam um pequeno detalhe, esse tópico tem 2 aninhos de vida e até agora nada.

Eu amo o Hibernate :slight_smile:

cmilfont

Mauricio Linhares:
Pois é, só percebam um pequeno detalhe, esse tópico tem 2 aninhos de vida e até agora nada.

Eu amo o Hibernate :)

Terminando mais um ano, Early Draft se preparando para gerar a versão final da JPA2 e nada de Criteria :slight_smile:

Mauricio_Linhares

Só o fato de não ter criteria e saveOrUpdate() mostram como JPA é um fiasco completo.

Leozin

JPA fica bom quando usado com a implementação do Hibernate e usado os JPATemplate do Spring

Daí sim fica bom (mesmo!)

luistiagos

Concordo em não ter criteria… algo mais inutil que ja vi é este criteria… para querys pequenas até vai mas vai pegar um relatorio filho da p**** pra fazer com uma porrada de campos e de tabelas e vai querer usar criteria pra fazer isto… não é nada trivial… vc vai se quebrar muito pra fazer isto em criteria… algo que vc tera uma dor de cabeça muito menor se fizer em hql com stringbuilders ou com bem menas dor de cabeça se fizer em sql nativo mesmo… ao meu ver coisas do tipo hql são uteis para pequenas consultas… este tipo de coisa não é muito bom pois vamos que o cliente ou o analista de negocios me peça a query da app para analisar? com criteria ou hql eu terei que refazer o sql nativo para mandar para ele pois o qual o hibernate gera é quase que ilegivel… e poucos teriam coragem de mandar algo daquele jeito… e se vc quiser testar em seu sgdb? mesma coisa… vc não vai ter como depurar o hql ou o criteria no seu sgdb… porem com sql nativo não tera problemas… alem disso hql e criteria tem uma curva de aprendizado longa… e no final toda aquela tranqueira de codigo vai virar sql nativo para ser executado… e quem vai fazer isto para vc? o framework… quem lhe garante que ele ira fazer da melhor forma? ja vi varios problemas de relatorios lentos por causa desses criterias e hqls da vida… acho que criteria e hql são bem vindos para coisas pequenas porem relatorios grandes eles só são uma dor de cabeça… agora criteria é algo totalmente fresco… montar querys via codigo pq não acha bonito colocar hqls ou sqls no codigo… o que isto acrescenta em desempenho, legibilidade, e em facil manutenção? acho que nada… alem do mais se analisar em questão de performace o framework tera que parsear sua query de acordo com seu criteria e isto ja é perca de performace…
acho que muitos pensão que ao usar um framework devem usar 100% dele e não o 100% dele que é devidamente util em seu projeto…

Mauricio_Linhares

Companheiro, criteria e HQL não existem para serem utilizadas pra fazer relatórios, se alguém lhe disse que deveria usar isso pra relatórios, avise ao seu companheiro que a proposta delas não é essa.

HQL e criteria são para montar consultas complexas entre objetos e não entre tabelas.

Outra coisa, por favor, use parágrafos, pontos finais e vírgulas no seu texto, ele é praticamente ininteligível.

cmilfont

luistiagos:
Concordo em não ter criteria… algo mais inutil que ja vi é este criteria… para querys pequenas até vai mas vai pegar um relatorio filho da p**** pra fazer com uma porrada de campos e de tabelas e vai querer usar criteria pra fazer isto… não é nada trivial… vc vai se quebrar muito pra fazer isto em criteria… algo que vc tera uma dor de cabeça muito menor se fizer em hql com stringbuilders ou com bem menas dor de cabeça se fizer em sql nativo mesmo… ao meu ver coisas do tipo hql são uteis para pequenas consultas… este tipo de coisa não é muito bom pois vamos que o cliente ou o analista de negocios me peça a query da app para analisar? com criteria ou hql eu terei que refazer o sql nativo para mandar para ele pois o qual o hibernate gera é quase que ilegivel… e poucos teriam coragem de mandar algo daquele jeito… e se vc quiser testar em seu sgdb? mesma coisa… vc não vai ter como depurar o hql ou o criteria no seu sgdb… porem com sql nativo não tera problemas… alem disso hql e criteria tem uma curva de aprendizado longa… e no final toda aquela tranqueira de codigo vai virar sql nativo para ser executado… e quem vai fazer isto para vc? o framework… quem lhe garante que ele ira fazer da melhor forma? ja vi varios problemas de relatorios lentos por causa desses criterias e hqls da vida… acho que criteria e hql são bem vindos para coisas pequenas porem relatorios grandes eles só são uma dor de cabeça… agora criteria é algo totalmente fresco… montar querys via codigo pq não acha bonito colocar hqls ou sqls no codigo… o que isto acrescenta em desempenho, legibilidade, e em facil manutenção? acho que nada… alem do mais se analisar em questão de performace o framework tera que parsear sua query de acordo com seu criteria e isto ja é perca de performace…
acho que muitos pensão que ao usar um framework devem usar 100% dele e não o 100% dele que é devidamente util em seu projeto…

Criteria é necessário para ORM, relatórios são basicamente sínteses de dados tabulados, você nunca deve usar uma ferramenta de ORM para gerar relatórios. se voce vai montar relatórios com HQL é algo totalmente estúpido.
Além do que relatório em tese você desenha em uma ferramenta como Crystal ou IReport, para que você usaria um ORM para isso?

cmilfont

Mauricio Linhares:
Companheiro, criteria e HQL não existem para serem utilizadas pra fazer relatórios, se alguém lhe disse que deveria usar isso pra relatórios, avise ao seu companheiro que a proposta delas não é essa.

HQL e criteria são para montar consultas complexas entre objetos e não entre tabelas.

Outra coisa, por favor, use parágrafos, pontos finais e vírgulas no seu texto, ele é praticamente ininteligível.

Lembrei dessa thread porque rolou discussão no CEJUG sobre um problema entre implementações da JPA. Ainda continuamos sem uma spec adequada de ORM, a JCP teimou com JDO durante tempos, agora está teimando com JPA sem Criteria :stuck_out_tongue:

Mas o que me espanta é que ainda não sabem para que é HQL, Criteria… enfim, ORM!

Mauricio_Linhares

Já faz tempo que eu desisti de esperar qualquer coisa decente do JCP, é muita politicagem num buraco só. Por isso que Java nunca vai ter nada comparável a LINQ, eles nunca vão conseguir convencer todos os vendors a implementar aquilo completo (assim como eles não conseguiram nem convencer eles a ter as suas próprias APIs de criteria).

Democracia não funciona nesses casos, ainda mais uma onde tanta gente pode meter o bedelho. O negócio é ignorar que isso existe e simplesmente continuar a utilizar o Hibernate.

L

Pegando o Early Draft Review da JSR 317, você vê na página 101 o seguinte trecho:

Portanto, calma. Ainda há uma chance das Criterias aparecerem.

cmilfont

Mauricio Linhares:
Já faz tempo que eu desisti de esperar qualquer coisa decente do JCP, é muita politicagem num buraco só. Por isso que Java nunca vai ter nada comparável a LINQ, eles nunca vão conseguir convencer todos os vendors a implementar aquilo completo (assim como eles não conseguiram nem convencer eles a ter as suas próprias APIs de criteria).

Democracia não funciona nesses casos, ainda mais uma onde tanta gente pode meter o bedelho. O negócio é ignorar que isso existe e simplesmente continuar a utilizar o Hibernate.

Acabei de escrever no blog sobre a Thread no CEJUG -> http://www.milfont.org/tech/2008/10/27/especificacao-ou-implementacao/
Problema é que não dá para simplesmente ignorar, porque a força de uma especificação tem muito peso nas decisões, o risco de sair da especificação é o que deixou a comunidade java tão presa [presa fácil] ao EJB2.
Se foi tão difícil convencer que aquilo era uma desgraça, imagina dizer hoje que ignorem EJB e JPA e continuem utilizando Spring e Hibernate!
A força de seguir a manada para muitos ainda é mais forte do que sustentar o melhor.

cmilfont

Leonardo3001:
Pegando o Early Draft Review da JSR 317, você vê na página 101 o seguinte trecho:

Portanto, calma. Ainda há uma chance das Criterias aparecerem.

Estão trabalhando por 2 anos na spec e não saiu nessa Draft, acho muito improvável que saia na próxima.

Mauricio_Linhares

Eu não consigo ver vantagem nenhuma em usar JPA, só desvantagens, não entendo com as pessoas podem continuar a usar isso e ainda achar que é bom.

cmilfont

Eu também não, o trabalho é convencer a manada a favor disso. Quantos projetos eu vejo o pessoal evitando usar Criteria para não ficar preso a implementação e se matando de Queries, ainda mais de NamedQuery via anotação :stuck_out_tongue:

ricardosoares

eu uso e abuso de consultas OO.
enquanto JPA não tiver, nem penso em adotar.

gostaria de ver esse DAO concatenando strings:
public List<Pessoa> findAllByCpfCnpj(String param) {
		if (param==null)
			param = "";
		else
			param = param.replaceAll("[^0-9]",""); // elimina caracters dif. de numeros
		if (param.equals("")) 
			return getHibernateTemplate().find("from Pessoa order by cpfCnpj");
		Long exato = Long.parseLong(param); // exemplo: "143"
		Criterion restri = Restrictions.eq("cpfCnpj", exato);
		int tam = param.length();
		String acresc = "0";
		while (acresc.length()+tam<=13) {
			Long de = Long.parseLong(param+acresc); // exemplo: "1430000"
			Long ate = Long.parseLong(param+acresc.replace('0', '9')); // exemplo: "1439999"
			restri = Restrictions.or(restri, Restrictions.between("cpfCnpj", de, ate));
			acresc = acresc+"0";
		}
		Long de = Long.parseLong(param+acresc);
		restri = Restrictions.or(restri, 
								 Restrictions.between("cpfCnpj", de, Long.MAX_VALUE));
		DetachedCriteria cri = DetachedCriteria.forClass(Pessoa.class)
									.add(restri).addOrder(Order.asc("cpfCnpj"));
		
        return getHibernateTemplate().findByCriteria(cri);
	}
ficaria abusardamente sujo.
plentz
ricardosoares:
eu uso e abuso de consultas OO. enquanto JPA não tiver, nem penso em adotar. gostaria de ver esse DAO concatenando strings:
public List<Pessoa> findAllByCpfCnpj(String param) {
		if (param==null)
			param = "";
		else
			param = param.replaceAll("[^0-9]",""); // elimina caracters dif. de numeros
		if (param.equals("")) 
			return getHibernateTemplate().find("from Pessoa order by cpfCnpj");
		Long exato = Long.parseLong(param); // exemplo: "143"
		Criterion restri = Restrictions.eq("cpfCnpj", exato);
		int tam = param.length();
		String acresc = "0";
		while (acresc.length()+tam<=13) {
			Long de = Long.parseLong(param+acresc); // exemplo: "1430000"
			Long ate = Long.parseLong(param+acresc.replace('0', '9')); // exemplo: "1439999"
			restri = Restrictions.or(restri, Restrictions.between("cpfCnpj", de, ate));
			acresc = acresc+"0";
		}
		Long de = Long.parseLong(param+acresc);
		restri = Restrictions.or(restri, 
								 Restrictions.between("cpfCnpj", de, Long.MAX_VALUE));
		DetachedCriteria cri = DetachedCriteria.forClass(Pessoa.class)
									.add(restri).addOrder(Order.asc("cpfCnpj"));
		
        return getHibernateTemplate().findByCriteria(cri);
	}
ficaria abusardamente sujo.

Ricardo, deixa eu te contar um segredo: ele já está absurdamente sujo :)

Paulo_Silveira

Leonardo3001:
Pegando o Early Draft Review da JSR 317, você vê na página 101 o seguinte trecho:

Portanto, calma. Ainda há uma chance das Criterias aparecerem.

Vao aparecer, ja confirmaram!

ricardosoares

plentz:

Ricardo, deixa eu te contar um segredo: ele já está absurdamente sujo :)

Tá aí uma coisa que não é segredo pra ninguém: q o código está sujo.

O que continua um segredo é: conseguir o mesmo resultado numa programação mais limpa.

Me ajuda a desvendar :?:

L

Desculpe reativar o tópico, mas é que já foi lançado o Public Draft Review do JPA 2.0, onde foi acrescentada a nova API de Criteria.

De acordo com a nova API, aquele exemplo acima (de buscar pessoas pelos primeiros dígitos do CPF/CNPJ) não ficaria tão feio assim. Veja:

public List<Pessoa> findAllByCpfCnpj(String param) {
        if (param == null) {
            param = "";
        } else {
            param = param.replaceAll("[^0-9]", ""); // elimina caracters dif. de numeros
        }

        QueryBuilder queryBuilder = em.getQueryBuilder();
        DomainObject pessoa = queryBuilder.createQueryDefinition(Pessoa.class);
        QueryDefinition qdef = pessoa.where(pessoa.get("cpfCnpj").like(param + "%"));

        Query q = em.createQuery(qdef);
        return q.getResultList();
    }

E aí, o que acharam?

moreirawebmaster

Desculpa a todos por está ressuscitando o topico.

Gostaria de dizer que JPA pra mim ainda tem que crescer muito, já utilizei ele em muitos projetos, mas… o Hibernate 4.0 e suas melhorias etc veio pra ficar, vale a pena sim investir no Hibernate, acredito que o JPA tem ainda sim uma longa estrada pela frente.

Abraços :roll: .

jaissonduarte

cara não sei mesmo do que vocês reclama :smiley:
pois mergulhei no JPA e não sei nada de Hibernate e JDBC
mas acho ela muito fera
se conhecesse os outros também reclamaria :twisted:
8)

seufagner

Como o RafaelRio citou, existem maneiras alternativas. Ainda, acho muito purismo usar Criteria se você resolve seu problema de outras formas.

Agora, se na tua aplicação você muda além de parâmetros condicionais, trechos da própria sentença, na minha opinião seu método tá muito “gordo”.

"Ah, então vou repetir a Query inteira se quiser acrescentar um GROUP BY ou HAVING diferente para cada caso?"
Bem eu acho no mínimo estranho o cara usar lógica para montar a Query de modo elegante. Cada query no seu lugar, chamada através de, quase sempre, um método que corresponde à sua ação especificamente. Ou talvez verificar se um único método deve ser tão responsável assim.

Na minha opinião criar uma extensão para a API só para evitar concatenações é forçar a barra demais.

[]s amigos!

Criado 23 de agosto de 2006
Ultima resposta 3 de mai. de 2007
Respostas 39
Participantes 21