Consulta com Distinct na API Criteria

Bom dia galera,

Estou com uma consulta pelo criteria e gostaria de usar o DISTINCT em um campo especifico, porém ela só me trás no campo chave da forma que eu estou fazendo.

public List consultarClassePorStringDistinct(String propriedade, String valor) {
        CriteriaBuilder builder = getEntityManager().getCriteriaBuilder();
        CriteriaQuery criteria = builder.createQuery(entityClass);
        Root root = criteria.from(entityClass);
        criteria.select(root);
        criteria.distinct(true);

        ParameterExpression<String> parametro = builder.parameter(String.class);
        criteria.where(builder.like(builder.lower(root.get(propriedade)), builder.lower(parametro)));

        criteria.orderBy(getEntityManager().getCriteriaBuilder().asc(root.get(propriedade)));
        TypedQuery query = getEntityManager().createQuery(criteria);
        query.setParameter(parametro, "%" + valor + "%");
//        query.setHint(QueryHints.CACHE_USAGE, CacheUsage.CheckCacheThenDatabase);
        return query.getResultList();
    }

Esse código retorna a seguinte Query:

SELECT DISTINCT ID, DATA_INICIO, DATA_REF, DATA_STATUS_CONC, DESCRICAO, ODEX, VALOR, VALOR_OBRIG_ESPC, CR FROM PARCIAIS_EDES_IMOBILIZADAS WHERE LOWER(DATA_REF) LIKE LOWER(?) ORDER BY DATA_REF ASC

Porém eu precisava que retornasse de acordo com a propriedade passada, que no caso é o DATA_REF, é possível fazer isso?

Projections.distinct(Projections.property("id"));

Creio que isso ajude.

Eu não estou usando o hibernate, então não tenho como usar a classe de Projections…

Estou usando a javax.persistence para importar o criteria.

Entendi.
Não havia prestado atenção nisso.

Consegui da seguinte forma:

public List consultarClassePorStringDistinct(String propriedade, String valor) {
        CriteriaBuilder builder = getEntityManager().getCriteriaBuilder();
        CriteriaQuery criteria = builder.createQuery(entityClass);
        Root root = criteria.from(entityClass);
        criteria.select(root.get(propriedade));
        criteria.distinct(true);

        ParameterExpression<String> parametro = builder.parameter(String.class);
        criteria.where(builder.like(builder.lower(root.get(propriedade)), builder.lower(parametro)));

        criteria.orderBy(getEntityManager().getCriteriaBuilder().asc(root.get(propriedade)));
        TypedQuery query = getEntityManager().createQuery(criteria);
        query.setParameter(parametro, "%" + valor + "%");
//        query.setHint(QueryHints.CACHE_USAGE, CacheUsage.CheckCacheThenDatabase);
        return query.getResultList();
    }

Acho extremamente verbosa a abordagem do CriteriaBuilder, prefiro, sem dúvidas, o JPQL.

1 curtida

Eu também, porém é o padrão que a empresa utiliza, então fico de mãos atadas.

Sei bem como é isso.

E essa foi uma consulta simples, imagina algo mais complexo.

Mesmo um simples “SELECT * FROM TABELA T” é complexo com essa maravilhosa solução.