O projeto nasceu com o intuito de agilizar o desenvolvimento das consultas de entidades do Hibernate em aplicações Java. Ao utilizar o Criteria do Hibernate nas tela de consulta de uma aplicação, comecei a desenvolver um projeto para agilizar estas consultas e também permitir que fossem mais genéricas a fim de reutilizar em toda aplicação.

Este projeto me rendeu uma diminuição de 80% de código-fonte durante o desenvolvimento de consultas.

Como funciona ?

A ideia é utilizar as entidades do Hibernate como objetos para filtrar uma consulta. Estes objetos seriam preenchidos com as condições que o usuário gostaria de filtrar. As classes do JPriuli-Filter criariam as queries do Hibernate dinamicamente a partir destes objetos; Ainda seria possível utilizar um único método para filtrar as consultas de qualquer entidade do sistema, permitindo que o código-fonte fique limpo.

O que preciso saber ?

A classe principal é a classe Filter, esta classe simplesmente armazena as condições que serão usadas para filtrar uma consulta.

net.priuli.filter

A interface Filter é utilizada para armazenar as condições para filtrar uma consulta. Esta interface é um Map

net.priuli.filter.utils.HibernateUtils

A classe acima transforma um Filter em um objeto Criteria do Hibernate. Os dados de um Filter são transformados em Restrictions e adicionados em um Criteria do Hibernate.

net.priuli.filter.utils.ScannerHibernateEntity

Esta classe faz algo similar ao Example.create(), todos os atributos de um objeto são percorridos e os valores não-nulos são utilizados para formar as restrições que serão usada na consulta, a diferença é que esta classe consegue obter os id de objetos de segundo nível,o example do hibernate não faz.

E o código ?

Primeiro faça o download da versão 1.2 ou 1.0 no Sourceforge.
Neste exemplo, imaginamos as entidades Cliente e Status, sendo que o Cliente pode ter um Status, e o Status pode ter N quantidade de Clientes.

@Entity
@Table(name="CLIENTE")
public class Cliente implements java.io.Serializable{

	private static final long serialVersionUID = 1L;

	@Id
	@Column(name="ID_CLIENTE")
	private Long id;
	
	@Column(name="NM_CLIENTE")
	private String nome;

	@ManyToOne(fetch=FetchType.EAGER)
	@JoinColumn(name="ID_STATUS")
	private Status status;

	//gets and sets

}

@Entity
@Table(name="STATUS")
public class Status implements java.io.Serializable{

	private static final long serialVersionUID = 1L;

	@Id
	@Column(name="ID_STATUS")
	private Long id;
	
	@Column(name="NM_STATUS")
	private String nome;

	//gets and sets

}

Agora o Filter começa entrar em ação:

Na camada DAO da aplicação, criaremos um método responsável por retornar uma lista de Cliente a partir do objeto Filter

//método de consulta
public List<Cliente> find(final Filter filter){
        //transformando o Filter em um objeto Criteria do hibernate
	Criteria criteria = HibernateUtils.buildCriteria( filter, session, persistentClass);
return criteria.list();

}

Agora precisaremos criar o filtro, para isso chamamos a classe FactoryFilter.createFilter() tal classe simplesmente cria implementações da interface Filter,.
Imaginamos que em algum momento precisamos buscar os clientes que tenham o nome de ‘Roberto’.

Filter filter = FactoryFilter.createFilter();
filter.addRestriction("nome","Roberto");
filter.changeLikeMode("nome", LikeMode.ANYWHERE);

List<Cliente> clientes = clienteDAO.find(filter);

No código acima criamos uma condição no Filter para buscar por todos os clientes que tem a palavra ‘%Roberto%’ no campo nome; A query ficaria assim:

SELECT * FROM CLIENTE WHERE NM_CLIENTE LIKE ‘%ROBERTO%’

Agora imaginamos que o usuário escolha o que ele quer filtrar em uma tela do sistema, o VRaptor, Jsf, etc, injeta a Entity/Objeto contendo as informações que o usuário digitou. Neste cenário podemos resolver desta maneira:


Filter filter = ScannerJPAEntity.parseRestrictions(this.cliente);

List<Cliente> clientes = clienteDAO.find(filter);

Os valores dos atributos do objeto ‘this.cliente’ serão convertidos pelo ScannerJPAEntity e adicionados automaticamente no Filter. Agora imagine, se você precisa criar um novo campo na Entidade Cliente e adicionar este campo na tela de consulta, a unica coisa que você precisará fazer será criar o campo na entidade e na tela pois as classes do JPriuli-Filter irá detecta via reflection os campos da entidade.

Como fazer join ?


Filter filter = FactoryFilter.createFilter();
filter.addRestriction("status.id",2L);

List<Cliente> clientes = clienteDAO.find(filter);
//todos os clientes que tenham o id do status igual a 2. JOIN

O projeto tem outras funcionalidades que não foram apresentadas neste post, como por exemplo: Paginação, Ordenação ASC/DESC, JOIN mas tem exemplos nos links abaixo:

Exemplo completo pode ser obtido neste link:
http://sourceforge.net/projects/priuli-filter/files/examples/ExamplePriuliFilterStandalone.zip/download
Exemplo camada DAO: Exemplo DAO

NOVA VERSÃO DISPONIBILIZADA: VERSÃO 2.0