Como evitar condicionais em um hql complexo sem utilizar criteria

Tenho a seguinte consulta, so estou colocando um trecho dela, pois tem + condicoes nela, como posso evitar este monte de if/else
sem utilizar criteria, alguem tem uma ideia para melhorar isso?

StringBuilder sb = new StringBuilder();
		sb.append(" SELECT p.prp_id FROM sns_proposta p ");
		sb.append(" LEFT JOIN sns_versao ver ON ver.ver_id = p.ver_id  LEFT JOIN sns_doc_normativo doc  ON doc.don_id = ver.don_id  ");
		sb.append(" LEFT JOIN sns_tipo_doc_normativo tip ON doc.tip_id = tip.tip_id LEFT JOIN sns_mac_processo mac ON mac.mac_id = doc.mac_id ");

		if (documentoNormativoSearch.getAreaAplicacao() != null) {
			sb.append(" LEFT JOIN sns_versao_area_aplicacao verAp on  verAp.ver_id = ver.ver_id ");
		}
		if (documentoNormativoSearch.getCategoriaDocumento() != null) {
			sb.append(" LEFT JOIN sns_escopo_documento escopo on escopo.ver_id = ver.ver_id ");
		}

		if (documentoNormativoSearch.getProcessoEstrategico() != null) {
			sb.append(" LEFT JOIN sns_processo_estrategico proE on proE.pre_id = ver.pre_id ");
		}

		if (documentoNormativoSearch.getProcessoOperacional() != null) {
			sb.append(" LEFT JOIN sns_processo_operacional proO on proO.pro_id = ver.pro_id ");
		}

		if (documentoNormativoSearch.getAtividade() != null) {
			sb.append(" LEFT JOIN sns_atividade ati  on ati.ati_id = ver.ati_id ");
		}

		if (documentoNormativoSearch.getAreaGestora() != null) {
			sb.append(" LEFT JOIN sns_area_gestora arg on arg.arg_id = ver.arg_id ");
		}
		if (documentoNormativoSearch.getAreaResponsavel() != null) {
			sb.append(" LEFT JOIN sns_area_unidade aun on aun.aun_id = ver.aun_id ");
		}

		sb.append(" WHERE");
		if (documentoNormativoSearch.getAreaAplicacao() != null) {
			sb.append("	verAp.aap_id = :areaAplicacao ");
			parameters.put("areaAplicacao", documentoNormativoSearch
					.getAreaAplicacao().getId());
			sb.append(" AND ");
		}

Essa é uma ótima questão. Vou acompanhar o tópico para ver o que o pessoal vai dizer a respeito dos “if`s mortos”.

[quote=lgGodoy]Tenho a seguinte consulta, so estou colocando um trecho dela, pois tem + condicoes nela, como posso evitar este monte de if/else
sem utilizar criteria, alguem tem uma ideia para melhorar isso?

[code]
StringBuilder sb = new StringBuilder();
sb.append(" SELECT p.prp_id FROM sns_proposta p “);
sb.append(” LEFT JOIN sns_versao ver ON ver.ver_id = p.ver_id LEFT JOIN sns_doc_normativo doc ON doc.don_id = ver.don_id “);
sb.append(” LEFT JOIN sns_tipo_doc_normativo tip ON doc.tip_id = tip.tip_id LEFT JOIN sns_mac_processo mac ON mac.mac_id = doc.mac_id ");

	if (documentoNormativoSearch.getAreaAplicacao() != null) {
		sb.append(" LEFT JOIN sns_versao_area_aplicacao verAp on  verAp.ver_id = ver.ver_id ");
	}
	if (documentoNormativoSearch.getCategoriaDocumento() != null) {
		sb.append(" LEFT JOIN sns_escopo_documento escopo on escopo.ver_id = ver.ver_id ");
	}

	if (documentoNormativoSearch.getProcessoEstrategico() != null) {
		sb.append(" LEFT JOIN sns_processo_estrategico proE on proE.pre_id = ver.pre_id ");
	}

	if (documentoNormativoSearch.getProcessoOperacional() != null) {
		sb.append(" LEFT JOIN sns_processo_operacional proO on proO.pro_id = ver.pro_id ");
	}

	if (documentoNormativoSearch.getAtividade() != null) {
		sb.append(" LEFT JOIN sns_atividade ati  on ati.ati_id = ver.ati_id ");
	}

	if (documentoNormativoSearch.getAreaGestora() != null) {
		sb.append(" LEFT JOIN sns_area_gestora arg on arg.arg_id = ver.arg_id ");
	}
	if (documentoNormativoSearch.getAreaResponsavel() != null) {
		sb.append(" LEFT JOIN sns_area_unidade aun on aun.aun_id = ver.aun_id ");
	}

	sb.append(" WHERE");
	if (documentoNormativoSearch.getAreaAplicacao() != null) {
		sb.append("	verAp.aap_id = :areaAplicacao ");
		parameters.put("areaAplicacao", documentoNormativoSearch
				.getAreaAplicacao().getId());
		sb.append(" AND ");
	}

[/code][/quote]

Cara, eu tinha este problema quando precisava montar querys SQL para JDBC, então comecei a aplicar o pattern Chain of responsibility, não removi os IF’s, mas eu organizei, não sei se é a melhor forma, porém eu gostei do resultado, rs.

Uma referencia:

[]'s

Consegui evitar os if’s vejam:
antes:

 if (documentoNormativoSearch.getAreaAplicacao() != null) {  
            sb.append(" LEFT JOIN sns_versao_area_aplicacao verAp on  verAp.ver_id = ver.ver_id ");  
        }  
        if (documentoNormativoSearch.getCategoriaDocumento() != null) {  
            sb.append(" LEFT JOIN sns_escopo_documento escopo on escopo.ver_id = ver.ver_id ");  
        }  
  
        if (documentoNormativoSearch.getProcessoEstrategico() != null) {  
            sb.append(" LEFT JOIN sns_processo_estrategico proE on proE.pre_id = ver.pre_id ");  
        }  
  
        if (documentoNormativoSearch.getProcessoOperacional() != null) {  
            sb.append(" LEFT JOIN sns_processo_operacional proO on proO.pro_id = ver.pro_id ");  
        }  
  
        if (documentoNormativoSearch.getAtividade() != null) {  
            sb.append(" LEFT JOIN sns_atividade ati  on ati.ati_id = ver.ati_id ");  
        }  
  
        if (documentoNormativoSearch.getAreaGestora() != null) {  
            sb.append(" LEFT JOIN sns_area_gestora arg on arg.arg_id = ver.arg_id ");  
        }  
        if (documentoNormativoSearch.getAreaResponsavel() != null) {  
            sb.append(" LEFT JOIN sns_area_unidade aun on aun.aun_id = ver.aun_id ");  
        }  

depois:



sb.append( ifNull(documentoNormativoSearch.getAreaAplicacao(),"",  "LEFT JOIN sns_versao_area_aplicacao verAp on  verAp.ver_id = ver.ver_id") );
sb.append( ifNulldocumentoNormativoSearch.getCategoriaDocumento(),"",  "LEFT JOIN sns_escopo_documento escopo on escopo.ver_id = ver.ver_id") );
sb.append( ifNull(documentoNormativoSearch.getProcessoEstrategico(),"",  "LEFT JOIN sns_processo_estrategico proE on proE.pre_id = ver.pre_id") );
sb.append( ifNull(documentoNormativoSearch.getProcessoOperacional(),"",  "LEFT JOIN sns_processo_operacional proO on proO.pro_id = ver.pro_id") );
sb.append( ifNull(documentoNormativoSearch.getAtividade(),"",  "LEFT JOIN sns_atividade ati  on ati.ati_id = ver.ati_id") );
sb.append( ifNull(documentoNormativoSearch.getAreaGestora(),"",  "LEFT JOIN sns_area_gestora arg on arg.arg_id = ver.arg_id ") );
sb.append( ifNull(documentoNormativoSearch.getAreaResponsavel(),"",  "LEFT JOIN sns_area_unidade aun on aun.aun_id = ver.aun_id ") );




	public static <T> T ifNull(T toCheck, T ifNull) {
		if (toCheck == null ||( toCheck instanceof String && StringUtils.isBlank((String) toCheck))) {
			return ifNull;
		}
		return toCheck;

	}
	

É, não sei se gosto dessa solução, eu acho que ainda prefiro os ifs, simplesmente porque fica mais fácil de entender.

E um detalhe, não tem pra que fazer um método genérico, se vai verificar o tipo, e só funciona se for String. Coloque String mesmo :slight_smile:

Não ele nao é so para String, ele aceita objetos ou qualquer tipo, so que qdo for String deve verificar se nao é espaco em branco/vazio.

[quote=lgGodoy]Não ele nao é so para String, ele aceita objetos ou qualquer tipo, so que qdo for String deve verificar se nao é espaco em branco/vazio.
[/quote]
Ah, verdade :slight_smile:

Você não se livrou dos ifs, apenas organizou de forma mais adequada. A abordagem ainda está utilizando ifs…

[quote=drsmachado]Você não se livrou dos ifs, apenas organizou de forma mais adequada. A abordagem ainda está utilizando ifs…[/quote]Pensei a mesma coisa. O.O

Acho que é impossível, pois se for analisar, os dados tem que entrar se, e somente se, alguma variável existir. Então em algum lugar vai ter que existir o tal do if.

Eu só queria imaginar algum jeito mais elegante de esconder ele, por enquanto não consegui pensar em nada. Talvez exista algum design pattern por aí que eu não conheço que se encaixe bem