Pesquisa - Como criar uma estrutura para pesquisa em java

Boa tarde pessoal,

Estou com uma duvida com relação a pesquisa no java, a dúvida é mais com relação a arquitetura ou estruta que devo utilizar. Vou colocar o exemplo da minha dúvida.

Bem… suponha que eu tenha uma classe Aluno e dentre os tantos atributos dela eu tenha também a dataCriacao e o status. O campo status eu posso ter varios status, Ex: A, B ou C.

Minha dúvida está na hora de montar uma pesquisa para o objeto aluno. Eu quero que o usuario possa colocar um Inicio e Fim para buscar aluno por dataCriacao e que ele possa pesquisar mais de um status de uma vez, ou seja, quero buscar os alunos que foram criados entre 01/01/2016 e 28/02/2016 e que possui o status A e B.

Qual a melhor estrutura para se montar essa pesquisa?

Vi em alguns lugares que eu posso criar uma Classe AlunoPesquisa ou AlunoFiltro e nessa classe colocar atributo status como uma lista e criar um atributo dataCriacaoIn e dataCriacaoFin. Mas fiquei na duvida se esse seria realmente a coisa certa a fazer porque eu estaria duplicando nessa classe filtro todos os atributos de Aluno.

Desde já agradeço a ajuda.

Fala @Wilian_Coelho

Para o que você precisa existem n formas de se fazer, mas as principais são: Consultas por HQL (JPQL), Consultas por Critérios (usando Criteria) e Consulta por Exemplos.

HQL - Linguagem de Consulta do Hibernate ou JPQL -> É um dialeto orientado para objetos, um sql bombado;

QBC - Query by Criteria - você monta sua consulta manipulando objetos de critérios em runtime;

QBE - Query by Example - você usa objetos populados com determinados valores e a consulta retorna todos que atendam esses valores no banco.

Veja os exemplos que montei pra você, considerando que vc já tenha a entidade Aluno com as propriedades que você mencionou.

1º Exemplo:

[CODE]
package exemplo;

import java.util.Arrays;
import java.util.Calendar;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.Query;

public class ConsultaPorHQL {

public static void main(String[] args) {
    EntityManager em = EntityManagerUtil.getEntityManager();

    em.getTransaction().begin();

    List<String> filtroStatus = Arrays.asList("A", "B", "C");

    StringBuilder sbQuery = new StringBuilder("from Aluno a where a.dataCriacao between :dtIni and :dtFim and a.status in (");

    for (int i = 0; i < filtroStatus.size(); i++) {
        sbQuery.append(":status").append(i).append(i == filtroStatus.size() - 1 ? "" : ", ");
    }
    sbQuery.append(")");

    Query qry = em.createQuery(sbQuery.toString())
            .setParameter("dtIni", Calendar.getInstance())
            .setParameter("dtFim", Calendar.getInstance());

    for (int i = 0; i < filtroStatus.size(); i++) {
        qry.setParameter("status" + i, filtroStatus.get(i));
    }

    List<Aluno> alunos = qry.getResultList();

    for (Aluno a : alunos) {
        System.out.println("Id: " + a.getId());
    }

    em.close();

}

}

[/CODE]

2º Exemplo:

[CODE]
package exemplo;

import java.util.Arrays;
import java.util.Calendar;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

public class ConsultaPorCriterios {

public static void main(String[] args) {
    EntityManager em = EntityManagerUtil.getEntityManager();

    em.getTransaction().begin();

    Calendar dtIni = Calendar.getInstance();
    Calendar dtFim = Calendar.getInstance();
    List<String> filtroStatus = Arrays.asList("A", "B", "C");

    CriteriaBuilder builder = em.getCriteriaBuilder();
    CriteriaQuery<Aluno> criteria = builder.createQuery(Aluno.class);
    Root<Aluno> root = criteria.from(Aluno.class);
    criteria.select(root);

    Predicate between = builder.between(root.get("dataCriacao"), dtIni, dtFim);
    Predicate in = root.get("status").in(filtroStatus);

    criteria.where(between, in);

    List<Aluno> alunos = em.createQuery(criteria).getResultList();

    for (Aluno a : alunos) {
        System.out.println("Id: " + a.getId());
    }

    em.getTransaction().commit();
    em.close();

}

}

[/CODE]

3º Exemplo:

[CODE]
package exemplo;

import java.util.Calendar;
import java.util.List;
import javax.persistence.EntityManager;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.Example;

public class ConsultaPorExemplos {

public static void main(String[] args) {
    EntityManager em = EntityManagerUtil.getEntityManager();

    Session session = (Session) em.getDelegate();

    Aluno filtroAluno = new Aluno();
    filtroAluno.setDataCriacao(Calendar.getInstance());
    filtroAluno.setStatus("B");

    Criteria criteria = session.createCriteria(Aluno.class);
    criteria.add(Example.create(filtroAluno));

    List<Aluno> alunos = criteria.list();

    for (Aluno a : alunos) {
        System.out.println("Id: " + a.getId());
    }
}

}

[/CODE]

Só lembrando que o 3º Exemplo, é usando a implementação hibernate direta, o certo é usar padrão jpa, mas foi só como exemplo pra ver que é possível, basta dar uma estuda.

Há também métodos depreciados como:

session.createCriteria(Aluno.class);

Ola @FernandoH

Primeiramente obrigado pela resposta e confesso que estou usando com a implementação direta do Hibernate, mas já estava pensando em mudar mesmo para o padrão JPA.

Hoje eu “acho que resolvi” meu problema de consulta criando um estrutura onde dentro da minha classe DAOAluno eu tenho o método consultar que esta da declarado como “public List consultar (AlunoPesquisa alunoPesquisa);”

AlunoPesquisa - Nessa classe eu tenho um atributo do tipo Aluno e os atributos DtIn, DtFim e um listStatus ou qualquer outro que só são utilizados nas consultas e buscas.

Usei a classe AlunoPesquisa como parâmetro porque dentro do método consultar eu verifico se determinado atributo do alunoPesquisa está preenchido e adiciono um filtro, hoje esta funcionando bem as consultas e está retornando os dados.

Quando digo que “acho que resolvi” é porque isso funciona, mas está correto usar assim? Será que estou fazendo da melhor forma?