Em todos os projetos no qual trabalhei sempre me deparei com uma situação muito incomoda, construir consultas sql utilizando strings. Isso é um verdadeiro “parto”.
Por mais que eu tentasse refatorar, organizar ou reutilizar nunca ficava bom e dificilmente a IDE te ajuda nessa tarefa e quando ajuda é de forma limitada.
Sim! você está sozinho nessa empreitada.
Queries dinâmicas cheias de “Ifs” totalmente ilegíveis e sem semântica alguma, alterações no banco de dados que refletem nas centenas de queries que você criou, descobrir apenas em produção que sua query está quebrada são apenas algumas das situação incomodas pelas quais passei e acredito que você também já tenha passado.

Um “if” incomoda muita gente…

745_especial_elefante
O exemplo abaixo mostra uma query dinâmica muito comum em diversos projetos.

StringBuilder sql = new StringBuilder();
sql.append("from Pessoa p where 1 = 1");
if(filtro.getNome() != null) {
    sql.append(" and p.nome = :nome");
}
if(filtro.getRg() != null) {
    sql.append(" and p.rg = :rg");
}
query = session.createQuery(sql.toString());
if(filtro.getNome() != null) {
    query.setString("nome", nome);
}
if(filtro.getRg() != null) {
   query.setString("rg", rg);
}

Nesse exemplo temos uma condição para incluir cada parâmetro na query e depois repetimos essas mesmas condições para atribuir os valores.
Agora imagine um consulta mais complexa com muitos parâmetros, você já deve estar irritado só de pensar na quantidade de “Ifs” repetidos sem falar nas inúmeras possibilidades de montar-las com erros.
Provavelmente você já deve estar pensando em formas melhores de construir essa query, talvez ate criar alguns builders pra eliminar essas repetição.

Um dia cansei de apanhar…

000_thumb
Depois de tanto sofrer resolvi buscar uma solução para esse problema. A primeira coisa que pensei foi:

Caramba! podia existir uma dsl em java pra construir queries

e foi então que encontrei um framework chamado Querydsl.
O Querydsl é um framework java que permite gerar queries type-safe com sintaxe similar ao JPQL, SQL e outras suportadas.

Confie na própria sombra

20070501201911-sombras
O Querydsl é compatível com as anotations do JPA. Através de um plugin do maven são criadas classes contendo todos os mapeamentos das suas entidades, uma espécie de sombra da entidade contendo variáveis estáticas. Dessa forma qualquer alteração no mapeamento será refletido nas classes do Querydsl.
Por padrão as classes do Querydsl possuem o mesmo nome das entidades acrescido do prefixo ”Q”. Ex: Entidade “Pessoa” gera “QPessoa”.
Configuração do plugin no maven

Matando um “if” por dia

Mgm-logo
Vamos agora utilizar o Querydsl para construir a mesma consulta do exemplo anterior.

JPAQuery query = new JPAQuery(entityManager);
query.from(QPessoa.pessoa);
if(filtro.getNome() != null) {
    query.where(QPessoa.pessoa.nome.eq(filtro.getNome()));
}
if(filtro.getRg() != null) {
    query.where(QPessoa.pessoa.rg.eq(filtro.getRg()));
}

Legal, agora nossa query ficou um pouco melhor, conseguimos eliminar os “Ifs repetidos e ainda ganhamos uma checagem em tempo de compilação garantindo que ela não vai quebrar em produção (Type-safe).
Nossa query melhorou mas precisa melhorar mais, deixar mais legível. Os “Ifs” criam uma quebra na leitura do código atrapalhando o entendimento do que ela realmente faz.

Valorize as pequenas coisas

11217155
O Querydsl tem algumas classes muito úteis que podem nos ajudar a melhorar nossa consulta, uma delas é a “com.mysema.query.BooleanBuilder”.
Essa classe vai nos permitir criar trechos reutilizáveis para compor nossa query de forma mais concisa.

JPAQuery query = new JPAQuery(entityManager);
query.from(QPessoa.pessoa)
      .where(
          nomeEq( filtro.getNome() )
          .and( rgEq(filtro.getRg()) )
      );
private BooleanBuilder nomeEq(String nome) {
    return filtro.getNome() != null
        ? new BooleanBuilder(QPessoa.pessoa.nome.eq(nome))
        : new BooleanBuilder();
}
private BooleanBuilder rgEq(String rg) {
    return filtro.getRg() != null
        ? new BooleanBuilder(QPessoa.pessoa.rg.eq(filtro.getRg()))
        : new BooleanBuilder();
}

Agora sim temos uma query mais legível, simples e elegante!
Mais um detalhe a ser observado é que podemos reutilizar esses helpers em outras queries ou seja podemos criar pedaços menores reutilizáveis e que possuam alguma semântica .

Conclusão

O objetivo desse artigo foi mostrar o que é o Querydsl e como ele pode resolver os problemas mais comuns na construção de queries. Os exemplos são bem simples e não mostram todo o potencial desse framework.
Com o Querydsl conseguimos criar queries elegantes e legíveis, eliminando “Ifs” e repetição de código. Também podemos incluir parâmetros de forma dinâmica através da criação de trechos de códigos reutilizáveis e semânticos, além da garantia de serem validadas em tempo de compilação (type-safe), garantindo que sua consulta sempre irá rodar.
Chega de sofrer! Construir queries pode ser divertido e seguro com Querydsl.

Autor

Bruno Garcia é desenvolver na Bluesoft há mais de 4 anos. Atualmente, ele lidera uma grande equipe de desenvolvedores que atua no módulo Financeiro do software da Bluesoft.

Deixe aqui o seu comentário