Problema com consulta usando Criteria/Hql

3 respostas
Ady_Junior

Boa tarde.

Estou com um problemas em realizar uma consulta, o problema esta descrito abaixo.

A consulta a ser realizada é:
Qual foi o CLIENTE que comprou os seguintes PRODUTOS:
Camisa Levis(id = 2), Calça conduta(id = 3) e Camisa calvin klein(id = 5)

Tenho 3 tabelas: Produto, Venda e Cliente.

Relacionamentos:
Produto 1:N Venda
Cliente 1:N Venda

Eu fiz a consulta com esse metodo:

public List<Cliente> listarClientesQueCompraramProdutos(List<Long> idsProdutos){
		DetachedCriteria dc = DetachedCriteria.forClass(Venda.class);		
		dc.createAlias("produto", "p");
		
		dc.add(Restrictions.in("p.id", idsProdutos));
		
		dc.setProjection(Projections.property("cliente"));
		
		return listar(dc);
	}

A consulta estatica em SQL ficaria assim:

SELECT c.id, c.nome
FROM produto as p 
INNER JOIN venda  as v ON p.id = v.produto_id
INNER JOIN cliente as c ON c.id = v.cliente_id
WHERE produto_id IN ( 2, 3, 5 )

O problema é que essa consulta me traz todos clientes que compraram qualquer um dos três produtos,
mais eu quero os que compraram todos os 3 produtos.

A clausula IN() faz um OR entre os elementos, mais pra funcionar deveria ser um AND,
mais eu não consegui fazer essa consulta, tentei de todas as formas, usei group by, distinct e não funcionou.

Alguém já realizou esse tipo de consulta e tem ela em Java/Criteia ou Hql ?

Obrigado.

3 Respostas

G

Acho que tu vai ter que fazer um for nesse seu array contendo os id’s e adicionar a condição AND pra cada um deles.

Ady_Junior

Obrigado pela dica grinche .

É exatamente o que eu pensei em fazer, mais eu não consigo fazer um AND nessa consulta para obter o resultado esperado ;/

Ady_Junior

Eu consegui resolver o problema via programação, mais o correto seria apenas fazer uma consulta para obter esses dados.
Do modo que eu fiz se gasta muita performance, por isso quero fazer utilizando apenas uma consulta.

Com o código a seguir eu consegui buscar os dados:

/**
	 * Deve listar qualquer cliente que tenha comprado TODOS os produtos passados pelo parametro idsProdutos.
	 * @param idsProdutos
	 * @return List<Cliente>
	 */
	public List<Cliente> listarClientesQueCompraramProdutos(List<Long> idsProdutos){
		if(idsProdutos == null || idsProdutos.isEmpty()){
			return null;
		}
		List<Cliente> listaClientesQueCompraramProdutos = new ArrayList<Cliente>();
		
		VendaDAO vendaDao = VendaDAO.getInstancia();
		
		// listo todos clientes que compraram 1 ou varios produtos contidos em [idsProdutos]
		List<Cliente> listaClientes = vendaDao.listarClientesProdutos(idsProdutos);
		
		
		if(listaClientes == null || listaClientes.isEmpty()){
			return null;
		}
		
		if(listaClientes.size() == 1){
			listaClientesQueCompraramProdutos.add(listaClientes.get(0));
			return listaClientesQueCompraramProdutos;
		}
		
		//busco todos os produtos que cada cliente obtido comprou, uma lista por cliente.
		Map<Cliente, List<Produto>> mapa = mapearProdutosPorCliente(listaClientes);
		
		
		//verifico se todos produtos que estao em [idsProdutos] estao contidos na lista de algum(ns) cliente(s) obtidos.
		for (Map.Entry<Cliente, List<Produto>> item: mapa.entrySet()) {
			
			if(verificarLista(idsProdutos, item.getValue())){
				listaClientesQueCompraramProdutos.add(item.getKey());
			}
		}
		
		return listaClientesQueCompraramProdutos;
	}

	public Map<Cliente, List<Produto>> mapearProdutosPorCliente(List<Cliente> listaCliente){
		Map<Cliente, List<Produto>> mapa = new HashMap<Cliente, List<Produto>>();
		
		for (Cliente cliente : listaCliente) {
			mapa.put(cliente, listarProdutosDoCliente(cliente));
		}
		
		return mapa;
	}

Consultas:

public List<Cliente> listarClientesProdutos(List<Long> idsProdutos){
		DetachedCriteria dc = DetachedCriteria.forClass(Venda.class);		
		dc.createAlias("produto", "p");
		
		dc.add(Restrictions.in("p.id", idsProdutos));
		
		dc.setProjection(Projections.property("cliente"));
		
		return listar(dc);
	}
	
	
	public List<Produto> listarProdutosDoCliente(Cliente cliente){
		DetachedCriteria dc = DetachedCriteria.forClass(Venda.class);		
		dc.createAlias("cliente", "c");
		
		dc.add(Restrictions.eq("c.id", cliente.getId()));
		
		dc.setProjection(Projections.property("produto"));
		
		return listar(dc);
	}

Se alguém souber realizar essa busca apenas com uma consulta me explica aqui por favor, que vai ajudar muito.

Vlw.

Criado 6 de outubro de 2012
Ultima resposta 12 de out. de 2012
Respostas 3
Participantes 2