Estoy tratando de poner a prueba un JPA repositorio. Aquí está mi cliente/código de prueba:

@Test
    public void testFindBoitesByMultiFieldWithIdentifiantSet() {
        BoiteDataOnDemand dod = new BoiteDataOnDemand();
        Boite boite = dod.getSpecificBoite(0);
        boite.setIdentifiant("theIdentifiant");
        boiteRepository.save(boite);
        assertEquals(10, Boite.countBoites());
        BoiteQueryInfo boiteQueryInfo = new BoiteQueryInfo();
        boiteQueryInfo.setIdentifiant("theIdentifiant");
        List<Boite> boites = boiteRepository.findBoitesByMultiField(boiteQueryInfo, 1, 5, "identifiant", "desc");
        assertEquals(1, boites.size());
    }

Aquí está el repositorio método:

@Override
    public List<Boite> findBoitesByMultiField(BoiteQueryInfo boiteQueryInfo, Integer firstResult_, Integer maxResults_, String sort_, String order_) {
        log.debug("findBoitesByMultiField");

        final String identifiant = boiteQueryInfo.getIdentifiant();
        final Date dateOuvertureFrom = boiteQueryInfo.getDateOuvertureFrom();

        CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
        CriteriaQuery<Boite> c = criteriaBuilder.createQuery(Boite.class);
        Root<Boite> boite = c.from(Boite.class);
        List<Predicate> criteria = new ArrayList<Predicate>();
            ...
        if (identifiant != null && !identifiant.trim().equals("")) {
            ParameterExpression<String> parameter = criteriaBuilder.parameter(String.class, "identifiant");
            Predicate condition = criteriaBuilder.like(boite.<String> get("identifiant"), parameter);
            criteria.add(condition);
        }

        if (dateOuvertureFrom != null && dateOuvertureTo != null) {
            ParameterExpression<Date> parameterDateOuvertureFrom = criteriaBuilder.parameter(Date.class, "dateOuvertureFrom");
            ParameterExpression<Date> parameterDateOuvertureTo = criteriaBuilder.parameter(Date.class, "dateOuvertureTo");
            Predicate condition = criteriaBuilder.between(boite.<Date> get("dateOuverture"), parameterDateOuvertureFrom, parameterDateOuvertureTo);
            criteria.add(condition);
        } else if (dateOuvertureFrom != null) {
            ParameterExpression<Date> parameter = criteriaBuilder.parameter(Date.class, "dateOuvertureFrom");
            Predicate condition = criteriaBuilder.greaterThanOrEqualTo(boite.<Date> get("dateOuverture"), parameter);
            criteria.add(condition);
        } else if (dateOuvertureTo != null) {
            ParameterExpression<Date> parameter = criteriaBuilder.parameter(Date.class, "dateOuvertureTo");
            Predicate condition = criteriaBuilder.lessThanOrEqualTo(boite.<Date> get("dateOuverture"), parameter);
            criteria.add(condition);
        }

            ...    
        if (order.equalsIgnoreCase("desc")) {
            c.orderBy(criteriaBuilder.desc(boite.get(sort)));
        } else {
            c.orderBy(criteriaBuilder.asc(boite.get(sort)));
        }

        for (Predicate predicate : criteria) {
            c.where(criteriaBuilder.and(predicate));
        }

        TypedQuery<Boite> q = em.createQuery(c);

        if (identifiant != null && !identifiant.trim().equals("")) {
            q.setParameter("identifiant", "%" + identifiant + "%");
        }

        if (dateOuvertureFrom != null && dateOuvertureTo != null) {
            q.setParameter("dateOuvertureFrom", dateOuvertureFrom);
            q.setParameter("dateOuvertureTo", dateOuvertureTo);
        } else if (dateOuvertureFrom != null) {
            q.setParameter("dateOuvertureFrom", dateOuvertureFrom);
        } else if (dateOuvertureTo != null) {
            q.setParameter("dateOuvertureTo", dateOuvertureTo);
        }

            ...    
        return q.setFirstResult(firstResult).setMaxResults(maxResults).getResultList();
    }

Sin embargo, la prueba siempre falla en assertEquals(1, boites.size()); lo que indica que no se devuelve el resultado es decir, ( java.lang.AssertionError: expected:<1> but was:<0> ).

Tengo la fuerte sospecha de que algo está mal aquí:

for (Predicate predicate : criteria) {
            c.where(criteriaBuilder.and(predicate));
        }

Pero no estoy seguro de cómo «y» los criterios.

Puede alguien por favor proporcionar asesoramiento?

P. S. FYI, BoiteDataOnDemand inserta al azar 10 filas en la boite tabla.

EDIT: código fue editada para hacerla más corta.

El código que has publicado es demasiado larga. Por favor, sólo publicar las partes pertinentes de la misma.
Me di por vencido en JPA criterios del API. QueryDSL con su fluent API es mucho más sencillo de entender y más concisa. Ver: queryDSL

OriginalEl autor balteo | 2012-09-03

2 Comentarios

  1. 21

    A partir de su sugerencia en la parte final de tu post, estoy de acuerdo en que la manera en que hay que agregar los predicados para el where cláusula no es correcta.

    Veo dos maneras de proceder:

    Primera forma

    La utilización de un conjunto de predicados

    List<Predicate> predicates = new ArrayList<Predicate>();
    for (Key key : keys) {
        predicates.add(criteriaBuilder.equal(root.get(key), value));
    }
    c.where(criteriaBuilder.and(predicates.toArray(new Predicate[] {})));

    Segunda forma

    Modificando el mismo predicado en el bucle

    Predicate predicate = criteriaBuilder.conjunction();
    for (Key key : keys) {
        Predicate newPredicate = criteriaBuilder.equal(root.get(key), value);
        predicate = criteriaBuilder.and(predicate, newPredicate);
    }
    c.where(predicate);

    EDITADO

    Después de mirar de nuevo el ejemplo de código, veo que usted ya ha creado en la manera correcta de una lista de PredicateS: han llamado criteria. Sólo está utilizando en el camino equivocado. Ver la última línea de mi primer ejemplo.


    EDITAR 2

    Para ver si el problema se genera por el uso de PredicateExpressionS, que no son específicamente necesarios en su caso, pruebe a quitar temporalmente. Modificar el primer criterio de

    if (identifiant != null && !identifiant.trim().equals("")) {
        ParameterExpression<String> parameter = criteriaBuilder.parameter(String.class, "identifiant");
        Predicate condition = criteriaBuilder.like(boite.<String> get("identifiant"), parameter);
        criteria.add(condition);
    }

    a

    if (identifiant != null && !identifiant.trim().equals("")) {
        Predicate condition = criteriaBuilder.like(boite.get("identifiant"), "%" + identifiant + "%");
        criteria.add(condition);
    }
    Gracias por tu aporte Perissf. Puede usted por favor decirme el tipo y valor de la value variable? Saludos.
    Que se acaba de pseudo-código. Usted puede utilizar su Predicados en su lugar. Usted probablemente no use el aro, pero el concepto es válido de todos modos por sus if cláusulas. Espero que sea claro.
    El comportamiento de mi examen es el mismo después de usar la última línea de su código, es decir, c.where(criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]))); Cualquier otra idea?
    He modificado el código como se recomienda en su segunda edición, así como la comentada la siguiente línea: q.setParameter("identifiant", "%" + identifiant + "%"); no hace ninguna diferencia por desgracia…
    Creo que: c.donde(criteriaBuilder.y(predicados.toArray(nuevo Predicado[] {})));es redundante, ya que podría ser reescrita como: c.donde(predicados.toArray(nuevo Predicado[] {}));

    OriginalEl autor perissf

  2. 0

    La solución completa que trabaja para mí es el siguiente:

            CriteriaBuilder builder = session.getCriteriaBuilder();
            CriteriaQuery<Object[]> criteriaQuery = builder.createQuery(Object[].class);
            Root<Eje> ejeRoot = criteriaQuery.from(Eje.class);
            Root<FactorCritico> factorRoot = criteriaQuery.from(FactorCritico.class);
    
    
            int factorParam = 2;
    
            criteriaQuery.multiselect(ejeRoot,factorRoot);
    
            List<Predicate> predicates = new ArrayList<>();
    
            Predicate ejeJoinFactorCritico = builder.equal(ejeRoot.get("id"), factorRoot.get("eje"));
            predicates.add(ejeJoinFactorCritico);   
    
            if (factorParam> 0){
                Predicate factorFilter = builder.equal(factorRoot.get("id"), factorParam);
                predicates.add(factorFilter);   
            }
    
            criteriaQuery.where(builder.and(predicates.toArray(new Predicate[] {})));
    
            Query<Object[]> query = session.createQuery(criteriaQuery);
            List<Object[]> resultList = query.getResultList();
    
            for(Object[] objects: resultList){
                Eje eje = (Eje) objects[0];
                System.out.println("eje: "+eje.getName());
    
                FactorCritico factor= (FactorCritico) objects[1];
                System.out.println("--> factor: "+factor.getName()+ ", eje: "+ factor.getEje().getName());
    
                //System.out.println("eje, factor size = "+eje.getFactorCriticos());
            }
    La explicación de la gran bloque de código sería útil para los lectores futuros
    Tengo una variable «factorParam’ utilizado como una bandera, si la variable es mayor que cero, entonces el Predicado objeto se agrega a un Predicado objeto de la lista, después de eso, la lista de predicado se agrega a donde frase.

    OriginalEl autor Jorge Santos Neill

Dejar respuesta

Please enter your comment!
Please enter your name here