Filter Dinamico para Hibernate

Desenvolvi um Filtro genérico e dinâmico para aplicações Java, faz 1 ano, e resolvi publicar como opensource, a idéia é um filtro dinâmico que através de reflection adiciona os critérios para um pesquisa, sem necessidade de criar queries hql ou Criteria do hibernate manualmente, é parecido com o Example do hibernate porem tem mais coisas para utilizar além de conseguir adicionar os id de objetos de segundo nível(relacionamento) que o Example do Hibernate deixa a desejar.

Vantagens em relação ao Example:

Consegue obter os ids de entity de segundo nivel
Mais genérico, pode ser utilizado em qualquer necessidade de Filtro.
Suporte para Paginação(Range)
Suporte para ordernar qualquer campo do objeto do 1 nivel.

Abrçs.

Tinha esquecido de disponibilizar o source…

https://sourceforge.net/projects/priuli-filter/files/priuli-filter_src_v1.0.zip/download

Nossa, vleu. Utilizei e ta agilizando muito meu projeto aqui.

Continuando com os meus estudos de Maven2, adicionei este filtro no repositório do Sonatype. Segue url:

https://oss.sonatype.org/content/groups/staging/net/priuli/

Cara esse seu Filter só funciona utilizando JSF ou dá para utilizá-lo com JSP (jstl+el) + vRaptor ?
Caso seja positivo, teria como explicar a forma de utilização?
Estou iniciando um novo projeto e gostaria de aplicar teu código.

Obrigado e parabéns pela iniciativa; espero contribuir de alguma forma.

[quote=softwork]Cara esse seu Filter só funciona utilizando JSF ou dá para utilizá-lo com JSP (jstl+el) + vRaptor ?
Caso seja positivo, teria como explicar a forma de utilização?
Estou iniciando um novo projeto e gostaria de aplicar teu código.

Obrigado e parabéns pela iniciativa; espero contribuir de alguma forma.[/quote]

Intão este filtro funciona com qualquer sistema que use Hibernate, pode ser web ou desktop (Standalone) eu uso ele em aplicação Jsf e aplicação Standalone mais ele não entra na camada de view intão pode ser usado em qualquer sistema que use hibernate.
As unicas implementações que crie foram para Hibernate, tem uma implementação que usa JPA1 + Hibernate. Mais pra frente tava pensando em criar outra implementação para o JPA2 que se não me engano vem com algo similar do criteria do hibernate.

Como usar não é muito dificil, no jsp ou vraptor vc faz sua chama normal da tela para o java( Logic/Component - vraptor) e na sua classe java, aquela que recebe o request, vc controi o filter com ajuda do ScannerHibernateEntity ou ScannerJPAEntity do meu proj ou então se não quizer a contrução da sua query automatica vc pode construir o filter na mão utilizando o FilterHashMapImpl ou impletar um.

Funciona assim vc controi um net.priuli.filter.Filter com os criterios de pesquisa e passa este filter, que tb é um HashMap, para seu dao e lá vc converte para criteria utilizando a classe net.priuli.filter.utils.HibernateUtils que transforma o Filter em Criteria, fazendo isso vc pode criar um DAO generico que contem esta funcionalidade ai pronto vc tem uma serie de consultas extremamente dinamica no seu sistema que pode ser usado por todas entidades, lembrando que é similar ao Example do hibernate, porem faz consultas de id até segundo nivel, tem paginação de resultados, ordenação de uma maneira generica.
Eu criei um exemplo para teste aqui: http://sourceforge.net/projects/priuli-filter/files/examples/
o svn tb está aqui: https://priuli-filter.svn.sourceforge.net/svnroot/priuli-filter

Mais duvidas é só postar, e se implementar algo vc pode contribuir tb!!

A melhor maneira que encontrei até agora foi esta, usando abstract dao generico que contem a funcionlidade de filtro.

public interface CRUD<T> {
	
	/**
	 * Carrega o objeto da base de dados.
	 * @param id - id do objeto
	 * @return objeto<T> - resultado da pesquisa.
	 */
	public T load(Long id);
	
	/**
	 * Atualiza ou cria um novo objeto na base de dados. 
	 * @param obj - o objeto
	 * @return T - o objeto atualizado
	 * @throws DAOException - Se ocorreu algum erro ao fazer a chamada ao banco.
	 */
	public T save(T obj) throws DAOException;
	/**
	 * Exclui o objeto da base de dados.
	 * @param obj - objeto a ser deletado
	 * @throws DAOException
	 */
	public void delete(T obj) throws DAOException;
	/**
	 * Pesquisa na base de dados de acordo com os criterios de pesquisa do filtro.
	 * @param filtro
	 * @return a pesquisa.
	 */
	public List<T> find(Filter filtro);
	/**
	 * Pesquisa na base de dados de acordo com os criterios de pesquisa do filtro.
	 * @param filtro
	 * @return a pesquisa.
	 */
	public T get(Filter filtro);
	/**
	 * Lista todos os objetos encontrados na base de dados.
	 * @return
	 */
	public List<T> list();
	/**
	 * Realiza uma contagem dos resultados encontrados para a pesquisa.
	 * @param filtro
	 * @return a quantidade de registros encontrados.
	 */
	public int count(final Filter filtro);

}

Depois eu crio uma classe abstrata que implementa o crud

public abstract class AbstractGenericDAO<T> implements CRUD<T>

	private Class<T> persistentClass;
	protected HibernateTemplate hibernateTemplate ;

	@Autowired
	public AbstractGenericDAO(Class<T> persistentClass, SessionFactory sessionFactory) {
		super();
		this.persistentClass = persistentClass;
		this.hibernateTemplate = new HibernateTemplate(sessionFactory);
	}

	public T load(final Long id){
		try{
			return (T) hibernateTemplate.execute( new HibernateCallback() {

				public Object doInHibernate(Session session) throws HibernateException {

					Criteria criteria = session.createCriteria(persistentClass);	
					criteria.add(Restrictions.eq("id",id));

					return criteria.uniqueResult();
				}
			});
		}catch(ObjectNotFoundException obf){
			return null;
		}
	}


	protected T update(T obj) throws DAOException{
		try{
			obj = (T) hibernateTemplate.merge(obj);
			hibernateTemplate.flush();

			return obj;
		}catch(Exception e){
			throw new DAOException("sua descricao do erro aqui",e);
		}
	}

	protected T create(T obj) throws DAOException{
		try{
			hibernateTemplate.save(obj);
			hibernateTemplate.flush();

			return obj;
		}catch(Exception e){
			throw new DAOException("sua descricao do erro aqui",e);
		}
	}

	@SuppressWarnings("unchecked")
	public List<T> find(final Filter filter){
		return hibernateTemplate.executeFind( new HibernateCallback() {

			public Object doInHibernate(Session session) throws HibernateException {

				Criteria criteria  = net.priuli.filter.utils.HibernateUtils.buildCriteria(filter, session, persistentClass);

				return criteria.list();
			}
		});
	}

	@SuppressWarnings("unchecked")
	public T get(Filter Filter){
		List list =  this.find(Filter);
		return uniqueResult(list);
	}

	@Override
	@SuppressWarnings("unchecked")
	public List<T> find(final Map<String, Object> filter) {
		return hibernateTemplate.executeFind( new HibernateCallback() {

			public Object doInHibernate(Session session) throws HibernateException {

				Criteria criteria  = net.priuli.filter.utils.HibernateUtils.buildCriteria(filter, session, persistentClass);

				return criteria.list();
			}
		});
	}

	@Override
	@SuppressWarnings("unchecked")
	public T get(Map<String, Object> filtro) {
		List list =  this.find(filtro);
		return uniqueResult(list);
	}


	@SuppressWarnings("unchecked")
	public List<T> list() {
		DetachedCriteria criteria = DetachedCriteria.forClass(persistentClass);
		return hibernateTemplate.findByCriteria(criteria)  ;
	}

	protected Session getSession(){
		return SessionFactoryUtils.getSession(hibernateTemplate.getSessionFactory(), true);
	}


	protected T uniqueResult(List<T> list ){
		if(list.size() > 0){
			return list.get(0);
		}else
			return null;
	}


}

com o dao generico não preciso fazer muito para ter as funcionalidade de filtro basta extender ela.

public interface ClienteDAO extends CRUD<Cliente>{
}

public class HibernateClienteDAO extends AbstractGenericDAO<Cliente> implements ClienteDAO{

	@Autowired
	public HibernateClienteDAO(SessionFactory sessionFactory) {
                                super(Cliente.class,sessionFactory);	
                }

	@Override
	public Cliente save(Cliente obj) throws DAOException {
		if (obj.getId()==null){
			return create(obj);
		}else{
			return update(obj);
		}		
	}
}

Usando seria algo assim:

Filter filter = FactoryFilter.createFilter("nome","Felipe");		
filter.addOrder(new Order("nome", Order.DESC));
//Buscando clientes que tenham nome like: 'Felipe%' (default) e ordenando DESC por nome"
List<Cliente> resultado = clienteDAO.find(filter);

ou assim:

Cliente cliente = new Cliente();
cliente.setNome("felipe");
Filter filter = net.priuli.filter.utils.ScannerHibernateEntity.parseRestrictions(cliente);		
filter.addOrder(new Order("nome", Order.DESC));
//Buscando clientes que tenham nome like: 'Felipe%' (default) e ordenando DESC por nome"
List<Cliente> resultado = clienteDAO.find(filter);

Há pedidos, fiz um refactoring no meu blog, onde tem a explicação deste projeto.
Deixei mais simples a explicação.

http://felipepriuli.wordpress.com/2010/10/12/priuli-filter/

Abrçs.

Estou trabalhando em uma nova versão, com as seguintes funcionalidades: 1.2

1º - Integração dom JPA2
2° - Ampliação da busca dos critérios, para alem do 2 nível de relacionamento
3º - Implementação de fetch type para os relacionamentos.

Versão 1.2 - Em andamento
Versão 1.1 - OSSRH-916

Olá Priuli tudo bom amigo ? Então, eu estava dando uma olhada no seu projeto e vi que você utiliza o Spring, bom eu ainda estou estudando o Spring mais ainda não consegui fazer nada, desenvolvo com flex (view) e estava realmente precisando muito de utilizar a biblioteca para critéria generica, eu tinha um pequeno projeto mais infelizmente perdi os dados do hd, estou utilizando dao generico, teria como me enviar um exemplo sem spring apenas com hibernate para ver se consigo dar continuidade ao meu desenvolvimento ? Fico no aguardo obrigado.

Este projeto em anexo é da versão 1.2 porem ainda esta em desenvolvimento, mas você pode ir vendo como funciona lá tem um exemplo.

Olá Priuli, como vai? Parabéns pelo projeto! Realmente é uma ótima opção em relação ao Example!

Porém, não filtra campos do tipo char?

Você chegou a disponibilizar o código desta versão 2.1 também? Só encontrei o da versão 1.0.

Obrigado,
Rogerio