Ainda não tem acesso? Estude com a gente! Matricule-se
Ainda não tem acesso? Estude com a gente! Matricule-se

Solucionado (ver solução)

No query defined for that name

Oi, gente! Tô tendo um probleminha ao executar queries de muitos pra muitos. Queries JPQL com join se recusam a executar. Fiz um teste no shell rodando um query parecido com inner join direto no SQL, e ele retorna certinho. Todos os outros métodos JPQL estão rodando certinho, somente esse que tem um join que tá me dando transtorno. De primeira achei que pudesse ser a persistence unit com entidades faltando, mas não é, todas estão lá. Podem dar uma força?

Query JPQL: SELECT m FROM Movimentacao m JOIN m.categoria c WHERE c = :pCategoria

Query SQL: SELECT * FROM Movimentacao m INNER JOIN Movimentacao_Categoria mc ON mc.Movimentacao_id = m.id;

Método que chama esse query:

@Test
public void testSelectMovimentacaoCategoriaParameter() {
        Categoria cat = new Categoria();
        cat.setId(1);

        String jpql = "SELECT m FROM Movimentacao m JOIN m.categoria c WHERE c = :pCategoria";
        Query query = em.createNamedQuery(jpql);
        query.setParameter("pCategoria", cat);

        List<Movimentacao> result = query.getResultList();
        result.forEach(mov -> {
            System.out.println("\n" + mov.toString() + "\n");
        });
}

Persistence unit declarada no persistence.xml:

<persistence-unit name="financas">
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
        <class>es.thalesalv.alura.jpa.model.Conta</class>
        <class>es.thalesalv.alura.jpa.model.Categoria</class>
        <class>es.thalesalv.alura.jpa.model.Cliente</class>
        <class>es.thalesalv.alura.jpa.model.Movimentacao</class>
        <properties>
            <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
            <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/financas"/>
            <property name="javax.persistence.jdbc.user" value="root"/>
            <property name="javax.persistence.jdbc.password" value="mysqlPassword"/>
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect"/>
            <property name="hibernate.hbm2ddl.auto" value="update"/>
            <property name="hibernate.show_sql" value="true"/>
            <property name="hibernate.format_sql" value="true"/>
        </properties>
    </persistence-unit>

Stacktrace do erro:

java.lang.IllegalArgumentException: No query defined for that name [SELECT m FROM Movimentacao m JOIN m.categoria c WHERE c = :pCategoria]
    at org.hibernate.internal.AbstractSharedSessionContract.buildQueryFromName(AbstractSharedSessionContract.java:812)
    at org.hibernate.internal.AbstractSharedSessionContract.createNamedQuery(AbstractSharedSessionContract.java:791)
    at org.hibernate.internal.AbstractSessionImpl.createNamedQuery(AbstractSessionImpl.java:23)
    at es.thalesalv.alura.jpa.model.JpqlTest.testSelectMovimentacaoCategoriaParameter(JpqlTest.java:26)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
3 respostas

Adendo: as operações do EntityManager não estão inclusas no método pois as coloquei nos métodos @Before, @BeforeClass e @After. Não estou criando milhares de main classes, e sim rodando com jUnit pra ficar tudo mais bonitinho e organizado. Não estranhem a falta dessas instruções ali.

solução

Thales, tudo bom?

Você está chamando o método createNamedQuery do EntityManager, e isso está causando o problema pois você está tentando executar uma query normal.

Use o método createQuery que recebe uma String com a declaração da query.

Se quiser ler mais sobre Named Queries, dê uma olhada neste link aqui (em inglês).

Um abraço e bons estudos!

Olá, Marcos, obrigado pela resposta!

Além disso que vc mencionou, achei outro problema na sintaxe do JPQL tbm: tive que ajustar WHERE c = :pCategoria para WHERE :pCategoria IN c por se tratar de uma lista. Agora tá tudo retornando certingo!

Obrigado!