Solucionado (ver solução)
Solucionado
(ver solução)
3
respostas

Função month da JPQL na Criteria API

Boa tarde pesssoal, tenho a seguinte JPQL:

select d from Diario d where month(d.horaInicio) = :pMes and d.usuario = :pUsuario

Como faria uso de algo similar à função month da JPQL?

3 respostas

com o CriteriaBuilder na mão, vc pode chamar a função function como descrita aqui => http://docs.oracle.com/javaee/7/api/javax/persistence/criteria/CriteriaBuilder.html#function-java.lang.String-java.lang.Class-javax.persistence.criteria.Expression...-

vc passa o nome da função que quer usar, o tipo de retorno dela e o parâmetro.

solução!

Olá Ygor,

O primeiro passo seria criar a CriteriaQuery e o Root baseados na entidade Diario:

CriteriaBuilder builder = manager.getCriteriaBuilder();
CriteriaQuery<Diario> criteria = builder.createQuery(Diario.class);
Root<Diario> root  = criteria.from(Diario.class);

Agora que temos o Root, podemos obter os Path para os campos pelos quais você deseja filtrar (no exemplo estou supondo que vc está utilizando a classe Calendar na data):

Path<Calendar> pathHoraInicio = root.<Calendar>get("horaInicio");
Path<Usuario> pathUsuario = root.<Usuariousuario");

Então obtemos um Predicate através do CriteriaBuilder, o qual representará todas as condições a serem concatenadas após o where da query:

Predicate conjunction = builder.conjunction();

O Predicate inicialmente não conterá nenhuma condição, então podemos criá-las e adicioná-las ao mesmo. Podemos usar o método function do CriteriaBuilder para criar uma expressão que representará a condição utilizando a função month. Este método recebe como parâmetro uma String que representa o nome da função, uma Classe que representará o tipo de retorno da função escolhida, e o path onde a mesma será aplicada. No seu caso ficaria algo como:

Expression<Integer> expression = builder.function("month", Integer.class, pathHoraInicio);

Uma vez que temos a Expression que representa a condição com a função, podemos adicioná-la ao Predicate criado anteriormente.

conjuntion = builder.and(conjunction, builder.equal(expression, mes));

Poderíamos fazer o mesmo para a outra condição que utiliza Usuario:

conjunction = builder.and(conjunction, builder.equal(pathUsuario, usuario));

Por fim, adicionamos o Predicateque agora contém todas as condições a nossa CriteriaQuery.

criteria.where(conjunction);

Agora é só criar uma query utilizando o EntityManager e a CriteriaQuery para obter o resultado:

criteria.where(conjunction);
manager.createQuery(criteria).getResultList();

O seu suposto método ficaria mais ou menos assim:

public List<Diario> listaPorMesEUsuario(Calendar mes, Usuario usuario){

  CriteriaBuilder builder = manager.getCriteriaBuilder();
  CriteriaQuery<Diario> criteria = builder.createQuery(Diario.class);
  Root<Diario> root  = criteria.from(Diario.class);

  Path<Calendar> pathHoraInicio = root.<Calendar>get("horaInicio");
  Path<Usuario> pathUsuario = root.<Usuario>get("usuario");

  Predicate conjunction = builder.conjunction(); 

  Expression<Integer> expression = builder.function("month", Integer.class, pathHoraInicio);

  conjuntion = builder.and(conjunction, builder.equal(expression, mes));
  conjunction = builder.and(conjunction, builder.equal(pathUsuario, usuario));

  criteria.where(conjunction);
  criteria.where(conjunction);
  manager.createQuery(criteria).getResultList();
}

Espero ter ajudado!

Valeu Alberto e Cássio! Vou dar uma olhada na documentação direitinho. E Cássio, sua ajuda foi muito didática, valeu mesmo!