Consultar jpql com o createQuery do EntityManager retornando erro

Estou tentando realizar a consulta abaixo, porém estou recebendo erro. Eu já tentei obter o ano de várias maneiras, mas nenhuma da certo, alguém poderia me ajudar?

Tentativas: to_char(…, ‘yyyy’)
to_date(…, ‘yyyy’)
Todas não são reconhecidas pelo entityManager.

public String findTeste() {
        String classe = MetaBaseAtivos.class.getName().toString();
        String nomePuro = classe.substring(classe.lastIndexOf(".") + 1, classe.length());
        StringBuilder sb = new StringBuilder();
        
        sb.append("select year(").append(nomePuro.toLowerCase()).append(".dataMeta) from ").append(nomePuro).append(" ").append(nomePuro.toLowerCase()).append(" ");
        sb.append(" where 1 = 1 and ").append(nomePuro.toLowerCase()).append(".codigo = 303231");
        
        javax.persistence.Query q = getEntityManager().createQuery(sb.toString());
        
        return (String) q.getSingleResult();
        
    }

Caused by: Exception [EclipseLink-0] (Eclipse Persistence Services - 2.7.0.v20170811-d680af5): org.eclipse.persistence.exceptions.JPQLException
Exception Description: Syntax error parsing [select year(metabaseativos.dataMeta) from MetaBaseAtivos metabaseativos where 1 = 1 and metabaseativos.codigo = 303231].
[10, 11] The SELECT clause has ‘year’ and ‘(metabaseativos.dataMeta)’ that are not separated by a comma.
at org.eclipse.persistence.internal.jpa.jpql.HermesParser.buildException(HermesParser.java:155)
at org.eclipse.persistence.internal.jpa.jpql.HermesParser.validate(HermesParser.java:334)
at org.eclipse.persistence.internal.jpa.jpql.HermesParser.populateQueryImp(HermesParser.java:278)
at org.eclipse.persistence.internal.jpa.jpql.HermesParser.buildQuery(HermesParser.java:163)
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.buildEJBQLDatabaseQuery(EJBQueryImpl.java:140)
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.buildEJBQLDatabaseQuery(EJBQueryImpl.java:116)
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.(EJBQueryImpl.java:102)
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.(EJBQueryImpl.java:86)
at org.eclipse.persistence.internal.jpa.EntityManagerImpl.createQuery(EntityManagerImpl.java:1741)
… 88 more

Para SQL use o método createNativeQuery.

Mas eu tenho várias outras consultas que seguem esse padrão, então não posso fugir disso.

Não existiria uma forma de se fazer isso como estou usando?

Você postou falando em “Consultar SQL”. Para SQL o método é createNativeQuery. createQuery é para hql/jpql.

Arrumei o tópico, desculpe pelo erro.

up

As funções acima só funcionam com query nativas.

Porque você não utiliza query nativa? Não há problema algum…
É como dizer: “Não vou usar LinkedList porque minha aplicação usa ArrayList”.

select extract (year from metabaseativos.datameta) from metabaseativos
2 curtidas

Mais ou menos. Se você precisar fazer uma migração de banco no futuro irá ter que transcrever tudo que está em query’s nativas para o análogo no novo banco. Eu optaria por escrever em hql também, mas ressalto que há algum trabalho a ser feito em termos de performance, quem já trabalhou com hibernate sabe do que estou falando.

De uma olhada no manual do hql:
https://docs.jboss.org/hibernate/orm/3.3/reference/en/html/queryhql.html#queryhql-expressions

Acredito que você encontre como escrever a query corretamente.

Essa query é bem simples até, apenas um extract.
Eu sei que a query funciona no MySQL, PostgreSQL e Oracle

Se por acaso ele não conseguir com jpql, terá que optar pela nativa mesmo e é bem rápida por sinal

Quando se trata de datas eu sempre usei nativeQuery, o problema seria a troca de banco mesmo, caso a empresa tivesse um banco X e esse banco o extract nao funcionaria, ai teria que ser jpql.

Eu sei que da pra fazer com Criteria a extração do ano, mas eu nunca fiz…

O problema é que a query que eu coloquei era apenas um teste que eu estava fazendo,

A que eu iria utilizar mesmo era mais trabalhosa, mas eu consegui fazer através do extract mesmo e com a createQuery.

StringBuilder sb = new StringBuilder();
        sb.append("select (SUM(").append(nomePuro.toLowerCase()).append(".valorImob)-SUM(").append(nomePuro.toLowerCase()).append(".valorObrig)) from ").append(nomePuro).append(" ").append(nomePuro.toLowerCase()).append(" ");
        sb.append(" where 1 = 1 and ").append(nomePuro.toLowerCase()).append(".ativo = 1");

        if(dataMeta != null) { 
            sb.append(" and extract(month from ").append(nomePuro.toLowerCase()).append(".data) = extract(month from :valorDataMeta)");
            sb.append(" and extract(year from ").append(nomePuro.toLowerCase()).append(".data) = extract(year from :valorDataMeta)");
        }
        if (area != null) {
            sb.append(" and ").append(nomePuro.toLowerCase()).append(".cr.idArea.codigo = :areaID ");
        }
        
        javax.persistence.Query q = getEntityManager().createQuery(sb.toString());

        if (area != null) {
            q.setParameter("areaID", area.getCodigo());
        }
        
        if(dataMeta != null) {
            q.setParameter("valorDataMeta", dataMeta);
        }

        return (BigDecimal) q.getSingleResult();
1 curtida