Olá pessoal.
Gostaria de saber se alguém pode me ajudar a utilizar a instrução in do CriteriaBuilder, considerando uma lista de valores (List) previamente carregada.
O código que segue abaixo, eu já sei que não funciona ( o problema está exatamente no momento de montar a instrução In que não sei como montar baseando-se em uma lista ).
Pesquisei sobre o assunto buscando no google, no guj, javaranch e no livro pro JPA 2.0, porém a única forma que mostram como usar o in, é utilizando a seguinte estrutura:
Porém a estrutura acima não me interessa, pois eu não conseguiria manter algo dinâmico como estou buscando.
Abaixo segue o exemplo de código onde eu gostaria de usar o In de forma mais efetiva:
public class CadastroProjetoServiceImpl implements CadastroProjetoService {
@PersistenceContext
private EntityManager em;
@Override
public List<Projeto> pesquisarProjetos(IConsultaProjetoTO projeto) throws CadastroException {
List<Projeto> lista = new ArrayList<Projeto>();
try {
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<Projeto> queryProjeto = builder.createQuery(Projeto.class);
Root<Projeto> projetoRoot = queryProjeto.from(Projeto.class);
queryProjeto.select(projetoRoot);
List<Predicate> predicados = new ArrayList<Predicate>();
// varios predicados construidos dinamicamente............
if (projeto.getListaStatusProjeto() != null && projeto.getListaStatusProjeto().size() > 0) {
predicados.add(builder.in(
projetoRoot.get(Projeto_.statusProjeto).in(
projeto.getListaStatusProjeto())));
}
// cria o where com as clausulas de filtro da select
if (predicados.size() > 0) {
queryProjeto.where(builder.and(predicados.toArray(new Predicate[]{})));
}
lista = em.createQuery(queryProjeto).getResultList();
} catch (PersistenceException e) {
throw new CadastroException(e);
}
return lista;
}
Obrigado.
Pessoal!
Faltou atenção ao ler o livro pro JPA 2 que define o seguinte:
Apenas para efeito de documentação, segue o código funcionando:
[code]public class CadastroProjetoServiceImpl implements CadastroProjetoService {
@PersistenceContext
private EntityManager em;
@Override
public List<Projeto> pesquisarProjetos(IConsultaProjetoTO projeto) throws CadastroException {
List<Projeto> lista = new ArrayList<Projeto>();
try {
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<Projeto> queryProjeto = builder.createQuery(Projeto.class);
Root<Projeto> projetoRoot = queryProjeto.from(Projeto.class);
queryProjeto.select(projetoRoot);
List<Predicate> predicados = new ArrayList<Predicate>();
// varios predicados construidos dinamicamente............
// agora não uso mais o builder.in e sim uma expression diretamente
if (projeto.getListaStatusProjeto() != null && projeto.getListaStatusProjeto().size() > 0) {
predicados.add(projetoRoot.get(Projeto_.statusProjeto).in(
projeto.getListaStatusProjeto()));
}
// cria o where com as clausulas de filtro da select
if (predicados.size() > 0) {
queryProjeto.where(builder.and(predicados.toArray(new Predicate[]{})));
}
lista = em.createQuery(queryProjeto).getResultList();
} catch (PersistenceException e) {
throw new CadastroException(e);
}
return lista;
}
[/code]
caso resolvido:
Uma coisa que notei que você teve que fazer é adicionar as restrições em um List e depois converter para arrays passando no CriteriaQuery.where. Acheo que nesse ponto a API pecou um pouco de você não poder chamar por várias vezes o where para ir adicionando dinamicamente elementos na where. Se você fizer isso apenas o último where funciona.
Outra coisa que senti falta é um ilike e um MatchMode. Quando eu fiz isso precisei usar um CriteriaBuilder.like + CriteriaBuilder.upper, e passar o curinga concatenando Strings.
Garcia,
realmente, você comentou uma situação a qual eu também tenho passado em relação à utilização de like:
Quanto ao where, eu também tentei executar o método mais de uma vez de modo que apenas o último where ficou como a cláusula válida.
Acredito que esta seria mesmo uma forma mais intuitiva.
Para isso a única forma que encontrei de deixar mais dinâmico foi criar uma lista de predicados p/ no final adicionar através do builder.and(listaDePredicados).
Eu gostei da API, porém o que ganhamos em dinamismo acaba-se perdendo por ter que escrever mais código.