JPA 2.0 CriteriaBuilder - In Expression

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.