EasyCriteria 3.0 – Novas funcionalidades

Olá, tudo bem?

É com muita felicidade que anuncio mais uma versão do EasyCriteria. E essa versão agora é para facilitar e ampliar e muito a utilização do framework (caso você não conheça e queira conhecer mais sobre o EasyCriteria clique aqui).

São 2 features e um enorme refactor nessa nova versão que o EasyCriteria até mereceu mudar a versão principal do framework de 2 para 3.

Vamos lá:

Extreme Refactoring

Houve uma refatoração no código onde foi reduzida a complexidade do código, aplicado padrões, atributos como “final” para melhorar alocação de memória e dependências do pom.

Versão 3.0
cobertura_30

Versão 2.2
cobertura_22

Note houve uma diminuição na complexidade ciclomática dos pacotes (mais sobre o teste de complexidade aqui). Apenas o pacote de utils que houve um singelo aumento da complexidade mas ainda assim com redução do número de linhas.

Joins Inifinitos! o/

Pode parecer coisa simples e básica, mas essa era, até essa versão, o maior desafio. Agora é possível fazer quantos joins forem necessários. Veja o código abaixo:

EasyCriteria<Person> easyCriteria = EasyCriteriaFactory.createQueryCriteria(getEntityManager(), Person.class);

easyCriteria.innerJoin("dogs.toys.manufacturer");

easyCriteria.andEquals("dogs.toys.manufacturer.name", "ACME");

easyCriteria.orderByDesc("dogs.toys.name");

Analisando a consulta acima é possível perceber que agora é possível fazer todos os joins desejados para as diversas funcionalidades já existentes. Veja que o método “andEquals” está atravessando os relacionamentos existentes na Entity Person.

É possível ver também que até a ordenação agora aceita os diversos tipos de join.

O que simplificará também a API do EasyCriteria, pois agora não será necessário chamar nenhum outro método que tenha Join em seu nome para criar um “where”. O método andJoinEquals (ou qualquer outro que tenha Join no nome fazendo condição, ex.: andJoinGreaterThan, andJoinStringIn, …) está deprecated e marcado para remoção em futuras versões.

Count

Esse método permite fazer um count no resultado da query. Veja o código abaixo:

EasyCriteria<Person> easyCriteria = EasyCriteriaFactory.createQueryCriteria(getEntityManager(), Person.class);
System.out.println(easyCriteria.count());

O código acima exibiria o total de Pessoas cadastradas no banco de dados. Mas, seria possível fazer algo mais avançado?

A query abaixo funcionaria sem problemas:

List<String> names = new ArrayList<String>();
names.add("John");
names.add("Mary");

EasyCriteria<Manufacturer> easyCriteria = EasyCriteriaFactory.createQueryCriteria(getEntityManager(), Manufacturer.class);
easyCriteria.setDistinctTrue();
easyCriteria.innerJoin("products.sellers");
easyCriteria.andStringNotIn("products.sellers.name", names);
easyCriteria.setFirstResult(0);
easyCriteria.setMaxResults(50);

System.out.println(easyCriteria.count());
List<Manufacturer> manufactures = easyCriteria.getResultList();

Note no código acima que com o EasyCriteria é possível realizar um “count” e com o mesmo objeto realizar a consulta necessária.

É importante ressaltar que: o método count ignorará os valores definidos em setMaxResults e setFirstResult. Atualmente para utilizar esse tipo de count com maxResults e firstReslt seria necessário realizar uma subquery e atualmente isso não é feito pelo framework.

100% de cobertura

E o projeto ainda continua com 100% de cobertura em testes unitários com OpenJPA, Hibernate e EclipseLink utilizando JUnit e o plugin Cobertura.

Espere que a ferramenta seja bastante útil a todos vocês.

Para utilizar basta adicionar a dependência no POM:

<dependency>
    <groupId>uaihebert.com</groupId>
    <artifactId>EasyCriteria</artifactId>
    <version>3.0.0</version>
</dependency>

Ou fazer o download do jar aqui: http://uaihebert.com/wp-content/uploads/EasyCriteria/EasyCriteria-3.0.0_2013-08-02.jar

Até mais pessoal. o_

22 thoughts on “EasyCriteria 3.0 – Novas funcionalidades

  1. Muito show a ferramenta Hebert, mais uma vez obrigado pela contribuição. Agora, tenho uma pergunta: é possível criar um orLike? Exemplo, passo um texto para pesquisar no nome ou sobrenome de uma pessoa, e cada dado está em uma coluna diferente da tabela. Seria algo como:

    SELECT * FROM Pessoa WHERE nome LIKE ‘%maria%’ OR sobrenome LIKE ‘%maria%’.

    É possível fazer isso com EasyCriteria 3.0?

    Abraços!

  2. Hebert parabéns!
    Venho acompanhando o projeto desde o primeiro release, e realmente foram mudanças consideráveis. A comunidade agradece o/

    Até mais.

    • Mauricio, boa tarde.

      Obrigado pelo apoio, fico feliz que você tenha gostado da ferramenta.

      Aos poucos estou trabalhando na nova versão. Já adicionei suporte a chave composta e hint, mas pretendo adicionar mais coisas.

      Até mais.

  3. Olá Hebert, parabéns pelo seu trabalho que me ajudou muito, tenho usado muito sua classe nas minhas aplicações, antigamente eu usava no meu repositório em um método gerérico passando um parametro para “cachear a consulta” exemplo:

    public List findFrom(String hsql,Integer firstRecord, Integer perPage, Boolean cache ) {

    TypedQuery query = null;

    if(hsql!=null){
    query = entityManager.createQuery(hsql,clazz);
    query.setHint(“org.hibernate.cacheable”,cache);
    }else{
    query = entityManager.createQuery(“FROM ” + clazz.getName(),clazz);
    query.setHint(“org.hibernate.cacheable”,cache);
    }

    if(perPage>0){
    query.setMaxResults( perPage );
    }
    if(firstRecord>0){
    query.setFirstResult( firstRecord );
    }

    List resultList = query.getResultList();

    return resultList;

    }

    Agora estou usando o easyCTO para passar a consulta a ser realizada:

    public List findByEasyCriteria(EasyCriteria easyCTO, Integer firstRecord, Integer perPage) {

    if(firstRecord>0){
    easyCTO.setFirstResult(firstRecord);
    }
    if(perPage>0){
    easyCTO.setMaxResults(perPage);
    }

    EasyCriteria easyCriteria = EasyCriteriaFactory.createQueryCriteria(entityManager, clazz, easyCTO);

    List resultList = easyCriteria.getResultList();

    return resultList;

    }

    O problema é , como faço para utilizar o “query.setHint(“org.hibernate.cacheable”,true);” ??? mesmo que não fique portável com outro Framework?

    • Marcos, boa tarde.

      Eu fiquei até com vergonha por ver que esqueci de colocar algo tão simples no EasyCriteria.

      Fiz até um commit rápido e já subir para o repositório uma versão que dá suporte a hints.

      Se quiser, posso te enviar o jar por email.

      Obrigado pela confiança. [=

  4. Seu framework tá muito legal, contudo não estou conseguindo subir na minha aplicação, eu tenho um ear com um projeto Web e um EJB, e estou importando no pom.xml do EJB, mas está dando essa mensagem de erro sempre: Caused by: java.lang.ClassNotFoundException: com.uaihebert.model.EasyCriteria

    • Jonathan, boa tarde.

      Verifique se o EasyCriteria está empacotado dentro do JAR.

      Se você está utilizando o CTO na parte Web você precisa fazer com que o jar seja visto por ele também.

      Você poderia colocar o jar dentro do próprio servidor, aí ele ficaria disponível para todos os artefatos.

      Obrigado pela visita.

  5. Olá Hebert!

    O Marcos Freitas me falou da sua classe e estou achando show de bola, ainda mais porque sou novato com Hibernate e essa api já facilitou muita coisa que eu estava achando complicado.

    Tenho uma dúvida, com ela eu consigo fazer select distinct sem ser do ID, por exemplo:

    Select distinct modelo from carros;

    Abraços e parabéns!

    • Ailton, boa tarde.

      Esse tipo de consulta ainda não é possível fazer, mas vou adicionar essa funcionalidade ao roadmap.

      Obrigado pelo apoio.

  6. Nessa versão, quando fazemos vários joins fetchs com base na mesma tabela, o SELECT gerado acaba repetindo a tabela inicial várias vezes.

    Exemplo:

    tenho uma tabela Funcionario que referencia a tabela Pessoa (idPessoa). A tabela pessoa, por sua vez referencia a tabela Cidade (idCidadeNascimento) e a tabela EstadoCivil (idEstadoCivil).

    Se eu coloco as seguintes instruções no meu criteria:

    criteria.leftJoinFetch(“pes.cidadeNascimento”);
    criteria.leftJoinFetch(“pes.estadoCivil”);

    O select gerado será mais ou menos assim:

    SELECT fun0.matricula, pes0.nome, pes1.nome, pes2.nome cid.nomeCidade, civ.nomeEstadoCivil FROM Funcionario fun0
    LEFT OUTER JOIN Pessoa pes0 ON fun0.idPessoa = pes0.idPessoa
    LEFT OUTER JOIN Pessoa pes1 ON fun0.idPessoa = pes1.idPessoa
    LEFT OUTER JOIN Pessoa pes2 ON fun0.idPessoa = pes2.idPessoa
    LEFT OUTER JOIN EstadoCivil civ ON pes1.idEstadoCivil = civ.idEstadoCivil
    LEFT OUTER JOIN Cidade cid0 ON pes2.idCidadeNascimento = cid0.idCidade

    Ou seja, para cada join é referenciada uma tabela Pessoa com um alias diferente. Isso faz com que o SELECT fique gigante, causando até um erro caso a quantidade de linhas ultrapasse um limite pré-estabelecido.

    Fiz um teste usando o Criteria do JPA, e esse comportamento não ocorre.

    Abs!

    • Felipe, boa tarde.

      Existe uma nova versão que estou desenvolvendo e espero lançar até outubro.

      Você se importaria em testar? Eu poderia te enviar o jar por email.

      Obrigado pela visita.

  7. Boa noite Hebert, gostei bastante do framework, inclusive eu conheci ele em um livro seu sobre JPA da casa do código. Só fiquei com dúvida, se você continua trabalhando no framework, se ainda sai alguma novidade, porque eu gostaria de utiliza-lo no meu sistema, porém eu senti falta da funcionalidade do OR Like por exemplo.

    Obrigado,
    Abraços.

    • Alisson, boa noite.

      Nesse caso existem diversos métodos que tem a opção de lowerCase. Basta passar o valor TRUE que tudo será feito. (:

      Obrigado pela visita.

Leave a Comment