Como fazer um SELECT dinâmico? [RESOLVIDO]

Pessoal,

Tenho que fazer uma consulta no banco (DAO), mas os campos que eu devo pesquisar (que vão no SELECT, NÃO no where) são dinâmicos.

A pessoa vai selecionar os campos (checkbox) e devo retornar para a tela os resultados apenas dos campos selecionados, não dos demais.

Dúvida:

Qual o melhor jeito de fazer isso? Retornar todos os dados (colocando todos os campos para pesquisar no banco) e tentar tratar no JSP (com JSTL?) ou fazer um alguma maneira de montar o SELECT com stringbuilder por exemplo?

[quote=Pacato]Pessoal,

Tenho que fazer uma consulta no banco (DAO), mas os campos que eu devo pesquisar (que vão no SELECT, NÃO no where) são dinâmicos.

A pessoa vai selecionar os campos (checkbox) e devo retornar para a tela os resultados apenas dos campos selecionados, não dos demais.

Dúvida:

Qual o melhor jeito de fazer isso? Retornar todos os dados (colocando todos os campos para pesquisar no banco) e tentar tratar no JSP (com JSTL?) ou fazer um alguma maneira de montar o SELECT com stringbuilder por exemplo?[/quote]

Acho que entendi o que quer. Traga tudo o que quer (no select usando asterisco *). Quando chegar no front-end, popule o que estiver checado e não popule o que estiver chacado. Pode fazer as verificações do que vai popular ou não usando javascript. Mas por que precisa fazer desta forma?
Na maioria das vezes, quando preciso fazer uma pesquisa por vários campos, eu faço select com like.
O ideal é que utilize algum ORM. JPA ou Hibernate. Se preferir fazer na mão seu SQLs, use prepared statements:
http://docs.oracle.com/javase/tutorial/jdbc/basics/prepared.html

cada caractere de interrogação será substituido de forma transparente pra vc, evitando problemas como de sql injection.

Olá Luiz obrigado pelo retorno…

Eu me deparei com isso pq é no SELECT, pois nas condições (WHERE) eu fiz outra vez assim:

[code]

private static final String SQL_ATUAL = " SELECT.... "+ "WHERE (";

public List listaMedGraf(List select) {
Connection conn = null;
PreparedStatement ps = null;
List listaMedGrafRelatorio = new ArrayList();

	if (!select.isEmpty()) {

sql.append(" Dispositivo.CodigoTecnologia IN (");
for (Iterator it = select.iterator(); it.hasNext():wink: {
it.next();
sql.append("?");
if (it.hasNext()) {
sql.append(",");
}
}
sql.append(")");
}

	try {

		conn = ConnectionManager.obterConexao();
		ps = conn.prepareStatement(SQL_ATUAL + sql.toString() + GROUP + ORDER);
		int indicePs = 1;

		if (!select.isEmpty()) {
			for (Integer i : select) {
				ps.setInt(indicePs++, i);
			}
		}

		ResultSet rs = ps.executeQuery();

		while (rs.next()) {

			ListaMedGraf listaRelatorio = new ListaMedGraf(
					rs.getString("CodTecnologia"),
					rs.getString("Operadora"), rs.getString("StatusSIMCard"),
					rs.getString("Quantidade"));

			listaMedGrafRelatorio.add(listaRelatorio);

		}

	} catch (Exception e) {
		e.printStackTrace();
	} finally {
		ConnectionManager.fecharConexao(conn, null, ps);
	}

	return listaMedGrafRelatorio;

}[/code]

Era passado uma lista de inteiro (códigos que deveriam ser pesquisados)…

Eu estava pensando em fazer algo similar… mas na hora de montar o result set, daria trabalho para montar o retorno…

Outro problema no meu caso é que estou mexendo com iframe… então a tela que abre de resultado não é a que estão os checkbox, então acho que com javascript não rola…

Se o problema for por causa do retorno, por que não devolve uma string em JSON pra este caso?

Pensando bem, eu não entendi o problema. To vendo que quer trabalhar com estatística.
Não sei se faria da mesma forma porque não sei como está estruturado seus dados e aparentemente que utilizar o mesmo fonte para várias tabelas.
Este tipo de ajuda não sei se pode ser dada em um forum. Acho que vai precisar de um analista ai pra fazer uma análise mais profunda.

O problema está assim…

Tenho umas páginas com JSP que são abertas dentro de um iframe

Uma destas telas ao abrir, consulto no BD de acordo com o que foi selecionado em uma outra página, para então voltar o valor.

Ai que está o problema, para eu montar o select não a condição dele.

Na tela de resultado trato com JSTL, mas não sei se ao consultar eu trato na classe entes de retornar…

vc pode dar 3 exemplos de como ficariam os selects? (String exemplo do qu quer). Talvez desta forma eu entenda um pouco como estão estruturados seus dados e exatamente o que quer.

Pelo que entendi, vc não pode retornar simplesmente uma lista de classes, pois seus conteúdos seriam muito dinâmicos. Por isso sugeri o JSON como retorno pois evitaria a necessidade de ter de escrever um Value Object para cada tipo de retorno. Neste caso, DAO, retornaria um ResultSet mesmo. E na classe final, antes de enviar ao cliente, converteria para JSON.

Como disse, só uma análise mais profunda para saber qual a melhor solução. Possivelmente, pro seu caso, terá até subselects. Não? Quem for sugerir a melhor opção pra vc vai precisar entender bem o que quer e a forma como foram estruturados seus dados. Acho que o que está querendo é muito genérico.

Sobre DTO:

Entendi Luiz…

Não tem subselect, é mais simples do que vc imagina…

é assim, tenho por exemplo, o campo idade, nome e matricula… Ai dessa vez só quero o nome, então o select só para trazer o nome:

SELECT nome from xxx where xxx

Agora quero nome e idade:

SELECT nome, idade from xxx where xxx

Fui mais claro? sou meio confuso para explicar rsrsrs…

e estes campos, são da página index (que serão fixos).
O resultado será em uma nova página que será carregada dentro do iframe…

[quote=Pacato]Entendi Luiz…

Não tem subselect, é mais simples do que vc imagina…

é assim, tenho por exemplo, o campo idade, nome e matricula… Ai dessa vez só quero o nome, então o select só para trazer o nome:

SELECT nome from xxx where xxx

Agora quero nome e idade:

SELECT nome, idade from xxx where xxx

Fui mais claro? sou meio confuso para explicar rsrsrs…

e estes campos, são da página index (que serão fixos).
O resultado será em uma nova página que será carregada dentro do iframe…
[/quote]

Então é exatamente como lhe sugeri no no primeiro reply. Traga tudo (*). O usuário não pode ver tudo o que tá no seu select?

Não… eu tenho que mostrar na tela apenas o resultado que ele escolheu, pois o que ele vai escolher é praticamente o título da tabela que trarei de resultado…

Então se ele não selecionou, então não posso mostrar a coluna com dado que ele não selecionou.

[quote=Pacato]Não… eu tenho que mostrar na tela apenas o resultado que ele escolheu, pois o que ele vai escolher é praticamente o título da tabela que trarei de resultado…

Então se ele não selecionou, então não posso mostrar a coluna com dado que ele não selecionou.[/quote]

Ok. Entendi.
Então, neste caso, sugeriria utilizar uma modal (que no momento de retorno verificaria o que está checado) ou passar esses valores via querystring (url) no momento de abrir seu iframe.

Se o dado está sendo checado pelo usuário, então ele teria a opção de ver o resultado. Se não tem, de forma nenhuma, porque ele não tem por seu perfil de acesso a opção de visualizar tal resultado, teria que ter um select diferente.

O melhor é mesmo trazer todos os campos (*) e de acordo com o checkbox (se modal) selecionado (ou variável da sua querystring na url se iframe) para criar ou não a coluna.

mais uma perguntinha… quantos campos teriam estas tabelas? mais de 40? Se vc paginar o resultado, não me preocuparia com o tamanho dos dados que estão trafegando para o cliente. mandaria tudo mesmo e lá no cliente o checkboxe selecionado determinaria se a coluna apareceria ou não. Na cláusula where, usaria like.

São 15 colunas… não é tanto assim…

Obrigado Luiz… vou dar uma tentada aqui com suas dicas e retorno com o resultado ok?

UÈ cada check possui um identificador é só ver quais estão checados e montar o select, por favor não faça select * … se sua aplicação crescer, logo log vai ficar um sistema lendo e gerar manutencao

lá alexafe blz?

o problema maior está em montar a lista depois disso… consegui montar um select de acordo com a seleção (coloco os campos em um array e verifico quais foram selecionados e envio para montar o SELECT) mas o problema está no retorno para formar a lista:

Aqui monto o select:


	private static final String SQL_SELECT_MED_GRAF = " SELECT ";
	private static final String SQL_WHERE_MED_GRAF = " FROM tb_telemetria WHERE cod_usuario = 1 ";


public List<ListaMedGraf> listaMedGraf(List<String> select) {
....
		if (!select.isEmpty()) {
			Iterator<String> it = select.iterator();
			while (it.hasNext()) {
			    String valor = it.next();
			    sql.append(valor);
			    if (it.hasNext()) {
			    	sql.append(", ");
			    }
			}
		}


try {

			conn = ConnectionManager.obterConexao();
			ps = conn.prepareStatement(SQL_SELECT_MED_GRAF + sql.toString() + SQL_WHERE_MED_GRAF);

[code]while (rs.next()) {

// MAS AQUI QUE TRAVA… COMO VOU MONTAR A LISTA? SE O SELECT É DINÂMICO?

			ListaMedGraf listaRelatorio = new ListaMedGraf(
					rs.getString("Cod"),
					rs.getString("Oper"), rs.getString("Status")
					);

			listaMedGrafRelatorio.add(listaRelatorio);

		}[/code]

Por esse problema estou pensando em trazer todo o resultado e depois eu separo verificando qual foi selecionado

User ResultSetMetaData aqui vc tem todas as informacoes do retorno da consulta, inclusive as coluna retornadas, da vc cria os objetos por reflexao e seta por reflexao e vai adicionando na lista assim fica dinamico :slight_smile:
Se vc nunca trabalhou com reflexao, estude por que vai resolver sua vida em muitos fatores.

Já ouvi falar, mas não faço ideia… vc teria algum exemplo por favor?

Não tenho nenhum exemplo agora, mas estude ResultSetMetaData que provem do ResultSet da consulta em jdbc e tb estude a reflexão, do seu caso para chamar métodos set e get por reflexão.

blz… vou dar uma estudada… é que tenho que entregar na semana que vem esse problema… caso eu não consiga por esse novo meio…

Valeu pela colaboração

N amontagem da lista?

ListaMedGraf listaRelatorio = new ListaMedGraf( rs.getString("Cod"), rs.getString("Ope"), rs.getString("Status") );

Como eu faria? é aqui que vc fala para usar essa reflexão?

vi um exemplo de resultsetmetadata:

Parece simples… mas não sei como eu montaria minha lista com o total de parâmetros corretos… pois pode ser que não retorne todos…

Vc iria fazer um for varrendo as colunas retornadas, dentro do for vc vai ter acesso a tudo que precisa é só olhar os metodoss de retorno do Result. dai vc ia criando o objeto , faria um for nos metodos do objeto, iri chamar os set do objeto por reflexao de acordo com as colunas retornadas, injetava os dados e adicionaria o objeto na lista, pronto :). Mais igual te falei tem que estudar reflexao. Se vc nao conseguir faz uma gambiarra qualquer e depois estuda e concerta rrss