Query dinâmica sem framework ORM

Com JDBC puro, como vcoês implementam uma query dinâmica?

Sempre fiz IFs dentro da classe, mas, há algum tempo atrás, conversando com o pessoal na faculdade, um cara me disse que isso é gambiarra (e realmente parece) e que isto deve ser resolvido com uma Stored Procedure na base.

Passei a adotar essa abordagem, mas hoje, com uma base Oracle que não é de nosso domínio, não consegui colocar a SP para funcionar. E, aquela história, prazo acabando, voltei a implementar na classe.

Eu já tinha a classe abaixo, e implementei um método toQueryString(). Assim:


import java.util.Date;

import br.com.celsomartins.date.DateService;

/**
 * POJO to be argument on DAO Query methods
 * @author Celso Martins
 * @since 15/04/2009
 */
public class ArsQuery {
	
	private Long arsNumber;
	private String solutionAgent;
	
	private Date initOpenedDate;
	private Date endOpenedDate;
	private Date initClosedDate;
	private Date endClosedDate;
	
	private Short status;
	private Short complexity;
	
	/**
	 * Transform the object's information in a plain String
	 */
	public String toString(){
		String format = "dd/MM/yyyy HH:mm:ss";
		return "[" + arsNumber + "]" + "[" + solutionAgent + "]" + "[" + status + "]" + "[" + complexity + "]" +
			"[" + DateService.formatDate(initOpenedDate, format) + "]" + 
			"[" + DateService.formatDate(endOpenedDate, format) + "]" +
			"[" + DateService.formatDate(initClosedDate, format) + "]" +
			"[" + DateService.formatDate(endClosedDate, format) + "]";
	}
	
	/**
	 * Build a dynamic query
	 * @return a String containing the dynamic query build
	 */
	public String toQueryString() {
		String sql = " SELECT * FROM tb_acc_ars_control ";
		
		if (arsNumber != null) {
			sql += " WHERE \"NUMBER\" = ? ";
		}
		
		if (solutionAgent != null) {
			sql += findConnector(sql) + " solutionAgent = ? ";
		}
		
		if ((initOpenedDate != null) && (endOpenedDate != null)) {
			sql += findConnector(sql) + " created BETWEEN ? AND ? ";
		}
		
		if ((initClosedDate != null) && (endClosedDate != null)) {
			sql += findConnector(sql) + " closed BETWEEN ? AND ? ";
		}
		
		if (complexity != null) {
			sql += findConnector(sql) + " score = ? ";
		}
		
		if (status != null) {
			sql += findConnector(sql) + " status = ? ";
		}
		
		return sql;
	}
	
	private String findConnector(String sql) {
		if (sql.toLowerCase().contains("where")) {
			return " AND ";
		}else {
			return " WHERE ";
		}
	}
}

Um dos meus incômodos é com o método findConnector que, apesar de não gostar, acho melhor que colocar o famoso (e famigerado) WHERE 1 = 1 ou WHERE NULL is NULL no início da query.

Como vocês implementam este tipo de coisa, quando não está usando Hibernate, iBatis…

P.S. Não reparem no poor english

Obrigado

olá.

perticularmente acho não gosto desse modelo de query dinamica. Se não usar JPA então faço query staticas. Criar atributos statics com a query nas minhas classes DAOs.

Acredito que existem várias abordagens para tal… considerar isto como gambiarra, eu não o faço. Pois já trabalhei em empresas que a única coisa que podia ficar em procedures eram métodos de importação de dados. Como citei são aboradagens e tals. Como geralmente trabalho com aplicações com DAOs definidos, eu trabalharia com esta montagem de query dentro de um DAO, assim se algum dia surgir um “hibernate da vida” na aplicação, eu somente trocaria os DAOs e não mecheria nas classes de domínio (POJOs).

Acredito que com um pouco de reflexão e algumas anotações podemos tirar esses “if’s” daí.

[]'s
JL

Não sei se entendi a questão mas aqui vai uma idéia.

Já utilizei algo assim:

// Este código poderia ficar em um arquivo de properties
String sql = "Select nom, endereco from Pessoa where codigo >= :codigoInicio and codigo <= :codigoFim"

DinamicQuery q = new DinamicQuery(sql);

q.setLong("codigoInicio", 100);
q.setLong("codigoFim", 500);

String query = q.createQuery();

// Executar a query

P.S O nome DinamicQuery se refere a uma classe que seria implementada por vc.

Espero ter ajudado.

flws

1 curtida

[quote=palmadias]olá.

perticularmente acho não gosto desse modelo de query dinamica. Se não usar JPA então faço query staticas. Criar atributos statics com a query nas minhas classes DAOs.

[/quote]

Não entendi. Como assim query estaticas? Seria implementar um método para cada combinação de campo?

Preciso dar uma olhada em JPA. Estou adiando isso indefinidamente. Acho que chegou a hora.

Existe mais um problema nessa abordagem que estou usando. Creio que serei obrigado a usar Statement, coisa que também não gosto. Cheguei bem próximo do que eu queria com stmt.getParameterMetaData(), mas acho que a quantidade de IFs seria interminável.

Creio que isso realmente não seja mais um POJO (Era quando a classe nasceu), pois, pelo que me lembro, um POJO é um método com getters, setters e um construtor. Só não entendi a relação entre POJO e classe de domínio.

[quote=Mero_Aprendiz]Acredito que com um pouco de reflexão e algumas anotações podemos tirar esses “if’s” daí.
[]'s
JL[/quote]

Vou dar uma olhada nisso também.

Tenho uma noção básica de reflexão, mas não consegui enxergar como me ajudaria.

Obrigado.

[quote=fantomas]Não sei se entendi a questão mas aqui vai uma idéia.

Já utilizei algo assim:

// Este código poderia ficar em um arquivo de properties
String sql = "Select nom, endereco from Pessoa where codigo >= :codigoInicio and codigo <= :codigoFim"

DinamicQuery q = new DinamicQuery(sql);

q.setLong("codigoInicio", 100);
q.setLong("codigoFim", 500);

String query = q.createQuery();

// Executar a query

P.S O nome DinamicQuery se refere a uma classe que seria implementada por vc.

Espero ter ajudado.

flws[/quote]

Creio que seja um caminho. Está abrindo um pouco a mente.

Mas a quantidade de parâmetros não será fixa, vai depender do que o usuário decidir preencher na JSP, antes de apertar o botão OK.

Acho que você confundiu um pouco com o bom e velho Delphi (o formato dos parâmetros) =)

Abraços.

Opa, tranquilão?

[quote=celso.martins]Com JDBC puro, como vcoês implementam uma query dinâmica?

Sempre fiz IFs dentro da classe, mas, há algum tempo atrás, conversando com o pessoal na faculdade, um cara me disse que isso é gambiarra (e realmente parece) e que isto deve ser resolvido com uma Stored Procedure na base.[/quote]

Preciso discordar. Seja em java ou plsql, classes ou stored procedures, não muda nada além do lugar. Se é gambiarra fazer na classe, também é fazer no banco.

Pra ter queries dinâmicas, sem um framework ORM, de maneira elegante… você vai praticamente ter que implementar o seu próprio mini-framework ORM. A solução que o fantomas propôs é um exemplo disso…

Agora… que mal lhe pergunte… porque cargas d’água você não usa um framework ORM cara?

[quote=frocchagas]…
Agora… que mal lhe pergunte… porque cargas d’água você não usa um framework ORM cara?[/quote]

Pois é, em primeira instância, porque não decido sozinho. :wink:

Durante o cachaçal na Lapa, decidimos utilizar o Hibernate.

[quote=celso.martins]
Acho que você confundiu um pouco com o bom e velho Delphi (o formato dos parâmetros) =)
Abraços.[/quote]

Durante o fim-de-semana, dei uma olhada em várias abordagens de persistência com o Java, para que essa semana fosse um pouco mais tranquila. Assim, percebi que no Java, também podemos nos referir ao parâmetros através de cadeias de Strings. Fato esse que eu ignorava solenemente. Desculpa a minha frase acima.

Abraços

ola bom dia pessoal vcs conhecem programadores plsq para pj

[quote=celso.martins]Com JDBC puro, como vcoês implementam uma query dinâmica?

Sempre fiz IFs dentro da classe, mas, há algum tempo atrás, conversando com o pessoal na faculdade, um cara me disse que isso é gambiarra (e realmente parece) e que isto deve ser resolvido com uma Stored Procedure na base.

Passei a adotar essa abordagem, mas hoje, com uma base Oracle que não é de nosso domínio, não consegui colocar a SP para funcionar. E, aquela história, prazo acabando, voltei a implementar na classe.
[/quote]

Para essa estratégia resultar vc precisa usar alguns padrões. o principal é o QueryObject. Neste padrão vc cria um objeto com os dados da query e delega a um Interpreter que a traduza para a tecnologias de pesquisa ( JDBC, Hibernate, Lucence, etc…)

Vc pode dar uma olhada no codigo do MiddleHeaven para ver como seria usando JDBC

Comece por:
http://code.google.com/p/middleheaven/source/browse/trunk/src/main/java/org/middleheaven/storage/db/dialects/PostgressDialect.java

e vá explorando. Especialmente PostgressCriteriaInterpreter.

O middleheaven é mais complexo que isso porque ele usa o conceito de dialeto e faz mais coisas que queries (ele controla tb creates e alter tables)

É um pouco complexo ao principio, mas depois é uma mão na roda.

Para a arquitetura geral refira-se a este artigo