Solucionado (ver solução)

Importante

Você está vendo a versão anterior da nova experiência da Alura que estamos preparando para você. Em breve, ela ganha uma identidade visual novinha totalmente pensada em potencializar seus estudos!

Solucionado
(ver solução)
20
respostas

Passando parâmetros na consulta JQPL com native query

Olá, como posso resolver o problema a seguir e eliminar um montão de strings passando parâmetros como o "asc" ou "desc" e o valor inicial e final do limit, se é que é possível, para a consulta em JQPL com native query, se não, como devo proceder?

    @Query(value = "SELECT * FROM ajax order by '%colName%' '%dir%' limit '%start%', '%end%'", 
            nativeQuery = true
    )
    List<JqueryDatatable> findByAjaxOrderBy(String colName, String dir, int start, int end);
20 respostas

Desse jeito aí, não vejo saída mesmo...

Você pode usar um método normal, escrevendo a query lá dentro.. Para minimizar os parâmetros, pode criar uma classe que possua essas informações que precisam ser colocadas na query e receber um objeto desse tipo aí.

Como tudo é parâmetro mesmo, vc não vai ter como fugir de passar eles, a ideia é apenas a minimizar a feiura :P.

solução!

Preciso saber se esta correto a forma que fiz! Se posso passar esse parâmetros em tempo de execução para a query?

é que isso tem cara de Spring Data JPA, não tem a ver especificamente com o Hibernate... Faltou vc colocar : antes dos nomes dos parâmetros.. E também associar cada parâmetro do método com o o da query. Teste e veja se da certo.

Nessa consulta esta retornando null, onde estou errando?

List<JqueryDatatable> listDt = jqueryDatatableService.searchByTermDirLimit(NOME_COLUNA, DIRECAO, INICIAR, QUANT_REGISTRO);
    @Transactional(readOnly = false)
    public List<JqueryDatatable> searchByTermDirLimit(String NOME_COLUNA, String DIRECAO, int INICIAR,
            int QUANT_REGISTRO) {
        return jqueryDatatableRepository.searchByTermDirLimit(NOME_COLUNA, DIRECAO, INICIAR, QUANT_REGISTRO);
    }
    @Query(value = "select * from ajax order by '%NOME_COLUNA%' '%DIRECAO%' limit '%INICIAR%', '%QUANT_REGISTRO%'", 
            nativeQuery = true
    )
    List<JqueryDatatable> searchByTermDirLimit(String NOME_COLUNA, String DIRECAO, int INICIAR, int QUANT_REGISTRO);

deixe a query simples, va incrementando e verifique o momento que passa a dar errado.

Null - o mesmo retorno! Tirei todos os parâmetros!

List<JqueryDatatable> listDt = jqueryDatatableService.searchByTermDirLimit();
    @Transactional(readOnly = false)
    public List<JqueryDatatable> searchByTermDirLimit() {
        return jqueryDatatableRepository.searchByTermDirLimit();
    }
    @Query(value = "select * from ajax", 
            nativeQuery = true
    )
    List<JqueryDatatable> searchByTermDirLimit();

é... não sei o que pode ser... pq o spring data jpa não retornaria nulo para uma lista e sim uma lista vazia..

Será que alguém aqui tem alguma sugestão para esse meu problema?

O erro!

cadê a linha 26 da classe JqueryDatatableService? Destaca a linha e coloca a classe toda.

A linha:

return jqueryDatatableRepository.searchByTermDirLimit();

a classe:

package br.com.augebit.contas.service;


import java.util.List;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import br.com.augebit.contas.entity.JqueryDatatable;
import br.com.augebit.contas.repository.JqueryDatatableRepository;

@Service
@Transactional(readOnly = true, propagation = Propagation.REQUIRED)
public class JqueryDatatableService {

    private JqueryDatatableRepository jqueryDatatableRepository;

    public List<JqueryDatatable> findAll() {

        return jqueryDatatableRepository.findAll();
    }

    @Transactional(readOnly = false)
    public List<JqueryDatatable> searchByTermDirLimit() {
        return jqueryDatatableRepository.searchByTermDirLimit();
    }
}

Estava faltando eu fazer a injeção da classe do repositório" com o @Autowired

a consulta agora me retorna:

Parameter with that position [1] did not exist.

Tem uma sugestão?

Falta vc injetar o dao.. marca o atributo com @Autowired.

Fiz a injeção e mudou a mensagem de erro para:

Parameter with that position [1] did not exist

Alterei a consulta no repositório e mesmo assim, ainda continua com a mensagem!

o código da consulta:

@Query(value = "select * from ajax order by '%NOME_COLUNA' '%DIRECAO' limit '%INICIAR', '%QUANT_REGISTRO'", 
            nativeQuery = true
    )
    List<JqueryDatatable> searchByTermDirLimit(
            @Param("NOME_COLUNA") String NOME_COLUNA,
            @Param("DIRECAO") String DIRECAO, 
            @Param("INICIAR") int INICIAR, 
            @Param("QUANT_REGISTRO") int QUANT_REGISTRO);

Se puder dar uma olhada, coloquei o projeto no GitHub:

https://github.com/klermann/demoDataTableSpringDataJpa

Olá Alberto. Conseguiu fazer rodar aqui a consulta JPQL. O código ficou assim:

    @Query(value = "select * from ajax order by :NOME_COLUNA :DIRECAO limit :INICIAR, :QUANT_REGISTRO", 
            nativeQuery = true
    )
    List<JqueryDatatable> searchByTermDirLimit(
            @Param("NOME_COLUNA") String NOME_COLUNA,
            @Param("DIRECAO") String DIRECAO, 
            @Param("INICIAR") int INICIAR, 
            @Param("QUANT_REGISTRO") int QUANT_REGISTRO);

e o hibernate faz a consulta assim, QUE NÃO É A QUE EU PRECISO! Hibernate: select * from ajax order by ? ? limit ?, ?

preciso que ordene por direção e quantidade de itens por página! Tem uma dica ai por favor?

está certo. Isso é só o log.. ele não mostra os valores aplicados.

Alberto, como devo implementar esse código para o Spring Data Jpa, lembrando que faz parte do mesmo código que me ajudou a resolver acima e que o projeto esta aqui https://github.com/klermann/demoDataTableSpringDataJpa.git

PreparedStatement stmt = con.prepareStatement(sql);
        ResultSet rs = stmt.executeQuery();

        while (rs.next()) {
            JSONArray ja = new JSONArray();
            ja.put(rs.getString("id"));
            ja.put(rs.getString("engine"));
            ja.put(rs.getString("browser"));
            ja.put(rs.getString("platform"));
            ja.put(rs.getString("version"));
            ja.put(rs.getString("grade"));
            array.put(ja);
        }
        stmt.close();
        rs.close();

Um for aqui seria a solução fazendo a iteração com o objeto vindo através da consulta em JPQL?

Consegui fazer dessa maneira, não sei se é mais correta...

List<JqueryDatatable> listDt = jqueryDatatableService.searchByTermDirLimit(NOME_COLUNA, DIRECAO, INICIAR, QUANT_REGISTRO);

        for(JqueryDatatable jqueryDataTable : listDt){

            JSONArray jaObj = new JSONArray();
            jaObj.put(jqueryDataTable.getId());
            jaObj.put(jqueryDataTable.getEngine());
            jaObj.put(jqueryDataTable.getBrowser());
            jaObj.put(jqueryDataTable.getPlatform());
            jaObj.put(jqueryDataTable.getVersion());
            jaObj.put(jqueryDataTable.getGrade());

            array.put(jaObj);
        }