Hibernate e Queries por Exemplos

Hibernate e Queries por Exemplos

Você já usou as queries do tipo Example no Hibernate? É uma mão na roda! Serve, principalmente, para fazer filtros de forma bastante simplificada. Como assim? Imagine que você tem um grid onde exibe os dados de uma entidade. Você aí precisa fazer filtros para o usuário pesquisar e exibir apenas os resultados que lhe interessa. Você, normalmente, vai colocar campos desta entidade para que o usuário informe um valor que será usado como filtro.

Imagine uma classe chamada Projeto, que está listada logo abaixo.

@Entity
@Table(name="AUDITA_PROJETO")
public class Projeto implements EntidadePersistente {

	@Id
	@GeneratedValue(strategy=GenerationType.AUTO)
	private Long id;

	@Column(name="IDENTIFICACAO")
	private String identificacao;

	@ManyToOne
	@JoinColumn(name="ID_TIPOPROJETO")
	private TipoProjeto tipoProjeto;

	@ManyToOne
	@JoinColumn(name="ID_SITUACAOPROJETO")
	private SituacaoProjeto situacaoProjeto;

	@Column(name="ATIVO")
	private Boolean ativo;

	@ManyToOne
	@JoinColumn(name="ID_REVISOR")
	private Usuario revisor;

	@ManyToOne
	@JoinColumn(name="ID_AUDITOR")
	private Usuario auditor;

	@Column(name="DATAINICIOPREVISTA")
	private Date dataInicioPrevista;

	@Column(name="DATAFIMPREVISTA")
	private Date dataFimPrevista;

	@ManyToOne
	@JoinColumn(name="ID_SETOR")
	private Setor setor;

      // Aqui vem todos Gets e Sets.

}

Você, então, quer fazer um filtro por Situação do Projeto e pelo Identificador do Projeto. Aí vai lá e coloca dois campos na tela: uma caixa de texto para o usuário digitar o identificador e um combobox para o usuário selecionar uma Situação. Certo? Mas, observe que a query será filtrada pelo identificador, mas não pela situação. Por que? Está dito na documentação do Hibernate: Version properties, identifiers and associations are ignored. By default, null valued properties are excluded.

E como resolver isto, então? Ahhh! Podemos usar reflexão para identificar as associações e colocar elas também! E como é isso? Bom, nossa primeira versão será esta aqui:

	private void gerarExemplosAninhados(Criteria criteria, E entidade) throws DAOException {
		Method[] methods = entidade.getClass().getMethods();
		for(Method method:methods) {

			// Verificar se é um "Get".
			if ( method.getName().indexOf("get") > -1 ) {
				try {
					Object o = method.invoke(entidade, null);
					if ( o instanceof EntidadePersistente ) {
						Example example = Example.create(o).enableLike(MatchMode.ANYWHERE).ignoreCase();
						String m = method.getName().substring(3);
						m = m.substring(0,1).toLowerCase() + m.substring(1);
						criteria.createCriteria(m).add(example);
					}
				} catch (IllegalArgumentException e) {
					throw new DAOException(e);
				} catch (IllegalAccessException e) {
					throw new DAOException(e);
				} catch (InvocationTargetException e) {
					throw new DAOException(e);
				}
			}
		}
	}

Entendeu? Este método ainda pode ser melhorado, é claro. Tratar melhor as exceções. Ir mais abaixo no aninhamento de classes. O que está sendo feito é basicamente “passear” por todos os métodos “get” da entidade e verificar aqueles que são também entidades mapeadas. No meu caso, eu sempre implemento a interface EntidadePersistente nestas classes, assim como você pode ver na entidade Projeto. Se for uma instância desta interface, então incluo ela no Criteria!

×