domingo, 23 de septiembre de 2018

Implementación de Consultas dinámicas en JPA

Hola.

Últimamente he estado trabajando en una migración de un sistema desde Visual Basic 6 (si, de cuando los perros se amarraban con longanizas) a Java 8.

Pensé que todo iría bien hasta que me tocó enfrentarme a las consultas con parámetros dinámicos. En este caso, se utiliza al Entity Manager y las Criteria Querys.

Y como soy de pocas palabras y mas acciones, dejo a continuación, el código con los imports necesarios para efectuar un método, traer un resultset paginado, el count del total de registros, generar los criterias y efectuar la lista de parámetros a manera de módulo separado para ahorrar trabajo.




import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service("controlFechaOrdeniaServiceImpl")
@Transactional
public class ControlFechaOrdeniaServiceImpl implements ControlFechaOrdeniaService {

    private final static Logger LOGGER = Logger.getLogger("");

    @PersistenceContext
    private EntityManager entityManager;

    @Autowired
    @Qualifier("controlFechaOrdeniaRepository")
    private ControlFechaOrdeniaRepository controlFechaOrdeniaRepository;

    private CriteriaBuilder criteriaBuilder;

    @Override
    public ControlFechaOrdeniaVO buscar(Integer paginaActual, Integer activos) throws Exception {

        ControlFechaOrdeniaVO controlFechaOrdenia = new ControlFechaOrdeniaVO();
        ControlFechaOrdenia filtro = new ControlFechaOrdenia();
        List<ControlFechaOrdenia> listaControlFechaOrdenia = null;

        controlFechaOrdenia.iniciarPaginador(paginaActual);

        if (activos != null) {
            filtro.setActivo(activos);
        }

        try {

            criteriaBuilder = entityManager.getCriteriaBuilder();

            listaControlFechaOrdenia = getRegistros(controlFechaOrdenia.getDesde(), filtro);
            controlFechaOrdenia.setListaControlOrdenia(listaControlFechaOrdenia);

            long totalRegistros = getCantidadRegistros(filtro);
            controlFechaOrdenia.setPaginado(totalRegistros);

            listaControlFechaOrdenia.stream().forEach(item -> { LOGGER.log(Constantes.LOG_LEVEL_INFO, "Id: "
            + item.getId()); });
            

        } catch (Exception ex) {
            LOGGER.log(Constantes.LOG_LEVEL_ERROR, "ControlFechaOrdeniaImpl.buscar");
            LOGGER.log(Constantes.LOG_LEVEL_ERROR, ex.getMessage());
        }

        return controlFechaOrdenia;

    }

    private List<ControlFechaOrdenia> getRegistros(int desde, ControlFechaOrdenia filtro) {
        
        List<Predicate> predicates = new ArrayList<Predicate>();
        List<ControlFechaOrdenia> listaControlFechaOrdenia = new ArrayList<>();
        TypedQuery<ControlFechaOrdenia> typedQuery;
        
        try {
            
            final CriteriaQuery<ControlFechaOrdenia> criteriaQuery = criteriaBuilder
                    .createQuery(ControlFechaOrdenia.class);
            final Root<ControlFechaOrdenia> entityRoot = criteriaQuery.from(ControlFechaOrdenia.class);

            predicates = this.getPredicateList(entityRoot, criteriaBuilder, filtro);
            
            criteriaQuery.orderBy(criteriaBuilder.asc(entityRoot.get("id")));
            criteriaQuery.where(criteriaBuilder.and(predicates.toArray(new Predicate[0])));

            typedQuery = entityManager.createQuery(criteriaQuery);
            typedQuery.setFirstResult(desde);
            typedQuery.setMaxResults(Constantes.REGISTROS_POR_PAGINA);

            listaControlFechaOrdenia = typedQuery.getResultList();

            return listaControlFechaOrdenia;
            
        } catch (Exception ex) {
            throw ex;
        }
    }

    public long getCantidadRegistros(ControlFechaOrdenia filtro) {

        List<Predicate> predicates = new ArrayList<Predicate>();

        try {

            final CriteriaQuery<Long> criteriaQuery = criteriaBuilder.createQuery(Long.class);
            Root<ControlFechaOrdenia> entityRoot = criteriaQuery.from(ControlFechaOrdenia.class);
            criteriaQuery.select(criteriaBuilder.count(entityRoot));

            predicates = this.getPredicateList(entityRoot, criteriaBuilder, filtro);
            
            criteriaQuery.where(predicates.toArray(new Predicate[predicates.size()]));

            TypedQuery<Long> typedQuery = entityManager.createQuery(criteriaQuery);

            return typedQuery.getSingleResult();

        } catch (Exception ex) {
            throw ex;
        }

    }

    private List<Predicate> getPredicateList(Root<ControlFechaOrdenia> entityRoot, CriteriaBuilder criteriaBuilder, ControlFechaOrdenia filtro) {

        List<Predicate> predicates = new ArrayList<Predicate>();

        if (filtro.getActivo() != null) {
            Predicate predicateFilter = criteriaBuilder.equal(entityRoot.get("activo"), filtro.getActivo());
            predicates.add(predicateFilter);
        }

        return predicates;
    }

}

Espero te sea de utilidad ;)